Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b06a514ce0 | |||
| 5b9dd8b80b | |||
| 55882ce783 |
@@ -1,33 +1,13 @@
|
||||
<!--- Provide a general summary of the issue in the Title above -->
|
||||
## Expected behaviour
|
||||
|
||||
## Expected Behavior
|
||||
<!--- If you're describing a bug, tell us what should happen -->
|
||||
<!--- If you're suggesting a change/improvement, tell us how it should work -->
|
||||
## Actual behaviour
|
||||
|
||||
## Current Behavior
|
||||
<!--- If describing a bug, tell us what happens instead of the expected behavior -->
|
||||
<!--- If suggesting a change/improvement, explain the difference from current behavior -->
|
||||
## Steps to reproduce the behaviour
|
||||
|
||||
## Possible Solution
|
||||
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
|
||||
<!--- or ideas how to implement the addition or change -->
|
||||
## Minio version
|
||||
- (paste output of `minio version`)
|
||||
|
||||
## System information
|
||||
|
||||
## Steps to Reproduce (for bugs)
|
||||
<!--- Provide a link to a live example, or an unambiguous set of steps to -->
|
||||
<!--- reproduce this bug. Include code to reproduce, if relevant -->
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
4.
|
||||
|
||||
## Context
|
||||
<!--- How has this issue affected you? What are you trying to accomplish? -->
|
||||
<!--- Providing context helps us come up with a solution that is most useful in the real world -->
|
||||
|
||||
## Your Environment
|
||||
<!--- Include as many relevant details about the environment you experienced the bug in -->
|
||||
* Version used (`minio version`):
|
||||
* Environment name and version (e.g. nginx 1.9.1):
|
||||
* Server type and version:
|
||||
* Operating System and version (`uname -a`):
|
||||
* Link to your project:
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
<!--- Provide a general summary of your changes in the Title above -->
|
||||
|
||||
## Description
|
||||
<!--- Describe your changes in detail -->
|
||||
|
||||
## Motivation and Context
|
||||
<!--- Why is this change required? What problem does it solve? -->
|
||||
<!--- If it fixes an open issue, please link to the issue here. -->
|
||||
|
||||
## How Has This Been Tested?
|
||||
<!--- Please describe in detail how you tested your changes. -->
|
||||
<!--- Include details of your testing environment, and the tests you ran to -->
|
||||
<!--- see how your change affects other areas of the code, etc. -->
|
||||
|
||||
## Types of changes
|
||||
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
|
||||
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
|
||||
|
||||
## Checklist:
|
||||
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
||||
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||
- [ ] My code follows the code style of this project.
|
||||
- [ ] My change requires a change to the documentation.
|
||||
- [ ] I have updated the documentation accordingly.
|
||||
- [ ] I have added tests to cover my changes.
|
||||
- [ ] All new and existing tests passed.
|
||||
@@ -1,42 +1,23 @@
|
||||
go_import_path: github.com/minio/minio
|
||||
sudo: required
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
dist: trusty
|
||||
|
||||
language: go
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
osx_image: xcode7.2
|
||||
|
||||
env:
|
||||
- ARCH=x86_64
|
||||
- ARCH=i686
|
||||
|
||||
script:
|
||||
## Run all the tests
|
||||
- make
|
||||
- diff -au <(gofmt -d cmd) <(printf "")
|
||||
- diff -au <(gofmt -d pkg) <(printf "")
|
||||
- make test GOFLAGS="-timeout 15m -race -v"
|
||||
- make test GOFLAGS="-race"
|
||||
- make coverage
|
||||
|
||||
# Refer https://blog.hypriot.com/post/setup-simple-ci-pipeline-for-arm-images/
|
||||
# push image
|
||||
- >
|
||||
if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$ARCH" == "x86_64" ]; then
|
||||
docker run --rm --privileged multiarch/qemu-user-static:register --reset
|
||||
docker build -t minio/minio:edge-armhf . -f Dockerfile.armhf
|
||||
docker build -t minio/minio:edge-aarch64 . -f Dockerfile.aarch64
|
||||
docker login -u="$DOCKER_USER" -p="$DOCKER_PASS"
|
||||
docker push minio/minio:edge-armhf
|
||||
docker push minio/minio:edge-aarch64
|
||||
fi
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
go:
|
||||
- 1.7.5
|
||||
- 1.6.2
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
### Install Golang
|
||||
|
||||
If you do not have a working Golang environment setup please follow [Golang Installation Guide](https://docs.minio.io/docs/how-to-install-golang).
|
||||
If you do not have a working Golang environment setup please follow [Golang Installation Guide](./INSTALLGO.md).
|
||||
|
||||
### Setup your Minio Github Repository
|
||||
Fork [Minio upstream](https://github.com/minio/minio/fork) source repository to your own personal repository. Copy the URL for minio from your personal github repo (you will need it for the `git clone` command below).
|
||||
|
||||
@@ -1,30 +1,19 @@
|
||||
FROM alpine:3.5
|
||||
FROM golang:1.6-alpine
|
||||
|
||||
MAINTAINER Minio Inc <dev@minio.io>
|
||||
WORKDIR /go/src/app
|
||||
ENV ALLOW_CONTAINER_ROOT=1
|
||||
|
||||
ENV GOPATH /go
|
||||
ENV PATH $PATH:$GOPATH/bin
|
||||
ENV CGO_ENABLED 0
|
||||
|
||||
WORKDIR /go/src/github.com/minio/
|
||||
|
||||
RUN \
|
||||
apk add --no-cache ca-certificates && \
|
||||
apk add --no-cache --virtual .build-deps git go musl-dev && \
|
||||
echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf && \
|
||||
go get -v -d github.com/minio/minio && \
|
||||
cd /go/src/github.com/minio/minio && \
|
||||
go install -v -ldflags "$(go run buildscripts/gen-ldflags.go)" && \
|
||||
rm -rf /go/pkg /go/src /usr/local/go && apk del .build-deps
|
||||
COPY . /go/src/app
|
||||
RUN \
|
||||
apk add --no-cache git bash && \
|
||||
go-wrapper download && \
|
||||
go-wrapper install -ldflags "`./buildscripts/docker-flags.sh`" && \
|
||||
mkdir -p /export/docker && \
|
||||
cp /go/src/app/docs/Docker.md /export/docker/ && \
|
||||
rm -rf /go/pkg /go/src && \
|
||||
apk del git bash
|
||||
|
||||
EXPOSE 9000
|
||||
|
||||
COPY buildscripts/docker-entrypoint.sh /usr/bin/
|
||||
|
||||
RUN chmod +x /usr/bin/docker-entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"]
|
||||
|
||||
ENTRYPOINT ["minio", "server"]
|
||||
VOLUME ["/export"]
|
||||
|
||||
CMD ["minio"]
|
||||
CMD ["/export"]
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
FROM resin/aarch64-alpine:3.5
|
||||
|
||||
MAINTAINER Minio Inc <dev@minio.io>
|
||||
|
||||
ENV GOPATH /go
|
||||
ENV PATH $PATH:$GOPATH/bin
|
||||
ENV CGO_ENABLED 0
|
||||
|
||||
WORKDIR /go/src/github.com/minio/
|
||||
|
||||
RUN \
|
||||
apk add --no-cache ca-certificates && \
|
||||
apk add --no-cache --virtual .build-deps git go musl-dev && \
|
||||
echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf && \
|
||||
go get -v -d github.com/minio/minio && \
|
||||
cd /go/src/github.com/minio/minio && \
|
||||
go install -v -ldflags "$(go run buildscripts/gen-ldflags.go)" && \
|
||||
rm -rf /go/pkg /go/src /usr/local/go && apk del .build-deps
|
||||
|
||||
EXPOSE 9000
|
||||
|
||||
COPY buildscripts/docker-entrypoint.sh /usr/bin/
|
||||
|
||||
RUN chmod +x /usr/bin/docker-entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"]
|
||||
|
||||
VOLUME ["/export"]
|
||||
|
||||
CMD ["minio"]
|
||||
@@ -1,30 +0,0 @@
|
||||
FROM resin/armhf-alpine:3.5
|
||||
|
||||
MAINTAINER Minio Inc <dev@minio.io>
|
||||
|
||||
ENV GOPATH /go
|
||||
ENV PATH $PATH:$GOPATH/bin
|
||||
ENV CGO_ENABLED 0
|
||||
|
||||
WORKDIR /go/src/github.com/minio/
|
||||
|
||||
RUN \
|
||||
apk add --no-cache ca-certificates && \
|
||||
apk add --no-cache --virtual .build-deps git go musl-dev && \
|
||||
echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf && \
|
||||
go get -v -d github.com/minio/minio && \
|
||||
cd /go/src/github.com/minio/minio && \
|
||||
go install -v -ldflags "$(go run buildscripts/gen-ldflags.go)" && \
|
||||
rm -rf /go/pkg /go/src /usr/local/go && apk del .build-deps
|
||||
|
||||
EXPOSE 9000
|
||||
|
||||
COPY buildscripts/docker-entrypoint.sh /usr/bin/
|
||||
|
||||
RUN chmod +x /usr/bin/docker-entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"]
|
||||
|
||||
VOLUME ["/export"]
|
||||
|
||||
CMD ["minio"]
|
||||
@@ -1,23 +0,0 @@
|
||||
FROM alpine:3.5
|
||||
|
||||
MAINTAINER Minio Inc <dev@minio.io>
|
||||
|
||||
RUN \
|
||||
apk add --no-cache ca-certificates && \
|
||||
apk add --no-cache --virtual .build-deps curl && \
|
||||
echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf && \
|
||||
curl https://dl.minio.io/server/minio/release/linux-amd64/minio > /usr/bin/minio && \
|
||||
chmod +x /usr/bin/minio && apk del .build-deps
|
||||
|
||||
EXPOSE 9000
|
||||
|
||||
COPY buildscripts/docker-entrypoint.sh /usr/bin/
|
||||
|
||||
RUN chmod +x /usr/bin/docker-entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"]
|
||||
|
||||
VOLUME ["/export"]
|
||||
|
||||
CMD ["minio"]
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
FROM resin/aarch64-alpine:3.5
|
||||
|
||||
MAINTAINER Minio Inc <dev@minio.io>
|
||||
|
||||
RUN \
|
||||
apk add --no-cache ca-certificates && \
|
||||
apk add --no-cache --virtual .build-deps curl && \
|
||||
echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf && \
|
||||
curl https://dl.minio.io/server/minio/release/linux-arm64/minio > /usr/bin/minio && \
|
||||
chmod +x /usr/bin/minio && apk del .build-deps
|
||||
|
||||
EXPOSE 9000
|
||||
|
||||
COPY buildscripts/docker-entrypoint.sh /usr/bin/
|
||||
|
||||
RUN chmod +x /usr/bin/docker-entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"]
|
||||
|
||||
VOLUME ["/export"]
|
||||
|
||||
CMD ["minio"]
|
||||
@@ -1,22 +0,0 @@
|
||||
FROM resin/armhf-alpine:3.5
|
||||
|
||||
MAINTAINER Minio Inc <dev@minio.io>
|
||||
|
||||
RUN \
|
||||
apk add --no-cache ca-certificates && \
|
||||
apk add --no-cache --virtual .build-deps curl && \
|
||||
echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf && \
|
||||
curl https://dl.minio.io/server/minio/release/linux-arm/minio > /usr/bin/minio && \
|
||||
chmod +x /usr/bin/minio && apk del .build-deps
|
||||
|
||||
EXPOSE 9000
|
||||
|
||||
COPY buildscripts/docker-entrypoint.sh /usr/bin/
|
||||
|
||||
RUN chmod +x /usr/bin/docker-entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/usr/bin/docker-entrypoint.sh"]
|
||||
|
||||
VOLUME ["/export"]
|
||||
|
||||
CMD ["minio"]
|
||||
@@ -18,7 +18,7 @@ $
|
||||
|
||||
- Run `go get foo/bar`
|
||||
- Edit your code to import foo/bar
|
||||
- Run `govendor add foo/bar` from top-level directory
|
||||
- Run `govendor add foo/bar` from top-level folder
|
||||
|
||||
#### Remove dependencies
|
||||
|
||||
|
||||
@@ -56,82 +56,78 @@ endif
|
||||
all: install
|
||||
|
||||
checks:
|
||||
@echo "Check deps"
|
||||
@echo "Checking deps:"
|
||||
@(env bash $(PWD)/buildscripts/checkdeps.sh)
|
||||
@echo "Checking project is in GOPATH"
|
||||
@(env bash $(PWD)/buildscripts/checkgopath.sh)
|
||||
|
||||
getdeps: checks
|
||||
@echo "Installing golint" && go get -u github.com/golang/lint/golint
|
||||
@echo "Installing gocyclo" && go get -u github.com/fzipp/gocyclo
|
||||
@echo "Installing deadcode" && go get -u github.com/remyoudompheng/go-misc/deadcode
|
||||
@echo "Installing misspell" && go get -u github.com/client9/misspell/cmd/misspell
|
||||
@echo "Installing ineffassign" && go get -u github.com/gordonklaus/ineffassign
|
||||
@go get -u github.com/golang/lint/golint && echo "Installed golint:"
|
||||
@go get -u github.com/fzipp/gocyclo && echo "Installed gocyclo:"
|
||||
@go get -u github.com/remyoudompheng/go-misc/deadcode && echo "Installed deadcode:"
|
||||
@go get -u github.com/client9/misspell/cmd/misspell && echo "Installed misspell:"
|
||||
@go get -u github.com/gordonklaus/ineffassign && echo "Installed ineffassign:"
|
||||
|
||||
verifiers: vet fmt lint cyclo spelling
|
||||
|
||||
vet:
|
||||
@echo "Running $@"
|
||||
@go tool vet -atomic -bool -copylocks -nilfunc -printf -shadow -rangeloops -unreachable -unsafeptr -unusedresult cmd
|
||||
@go tool vet -atomic -bool -copylocks -nilfunc -printf -shadow -rangeloops -unreachable -unsafeptr -unusedresult pkg
|
||||
@echo "Running $@:"
|
||||
@GO15VENDOREXPERIMENT=1 go tool vet -all ./cmd
|
||||
@GO15VENDOREXPERIMENT=1 go tool vet -all ./pkg
|
||||
@GO15VENDOREXPERIMENT=1 go tool vet -shadow=true ./cmd
|
||||
@GO15VENDOREXPERIMENT=1 go tool vet -shadow=true ./pkg
|
||||
|
||||
fmt:
|
||||
@echo "Running $@"
|
||||
@gofmt -d cmd
|
||||
@gofmt -d pkg
|
||||
@echo "Running $@:"
|
||||
@GO15VENDOREXPERIMENT=1 gofmt -s -l cmd
|
||||
@GO15VENDOREXPERIMENT=1 gofmt -s -l pkg
|
||||
|
||||
lint:
|
||||
@echo "Running $@"
|
||||
@${GOPATH}/bin/golint -set_exit_status github.com/minio/minio/cmd...
|
||||
@${GOPATH}/bin/golint -set_exit_status github.com/minio/minio/pkg...
|
||||
@echo "Running $@:"
|
||||
@GO15VENDOREXPERIMENT=1 ${GOPATH}/bin/golint github.com/minio/minio/cmd...
|
||||
@GO15VENDOREXPERIMENT=1 ${GOPATH}/bin/golint github.com/minio/minio/pkg...
|
||||
|
||||
ineffassign:
|
||||
@echo "Running $@"
|
||||
@${GOPATH}/bin/ineffassign .
|
||||
@echo "Running $@:"
|
||||
@GO15VENDOREXPERIMENT=1 ${GOPATH}/bin/ineffassign .
|
||||
|
||||
cyclo:
|
||||
@echo "Running $@"
|
||||
@${GOPATH}/bin/gocyclo -over 100 cmd
|
||||
@${GOPATH}/bin/gocyclo -over 100 pkg
|
||||
@echo "Running $@:"
|
||||
@GO15VENDOREXPERIMENT=1 ${GOPATH}/bin/gocyclo -over 65 cmd
|
||||
@GO15VENDOREXPERIMENT=1 ${GOPATH}/bin/gocyclo -over 65 pkg
|
||||
|
||||
build: getdeps verifiers $(UI_ASSETS)
|
||||
|
||||
deadcode:
|
||||
@${GOPATH}/bin/deadcode
|
||||
@GO15VENDOREXPERIMENT=1 ${GOPATH}/bin/deadcode
|
||||
|
||||
spelling:
|
||||
@${GOPATH}/bin/misspell -error `find cmd/`
|
||||
@${GOPATH}/bin/misspell -error `find pkg/`
|
||||
@${GOPATH}/bin/misspell -error `find docs/`
|
||||
@GO15VENDOREXPERIMENT=1 ${GOPATH}/bin/misspell -error cmd/**/*
|
||||
@GO15VENDOREXPERIMENT=1 ${GOPATH}/bin/misspell -error pkg/**/*
|
||||
|
||||
test: build
|
||||
@echo "Running all minio testing"
|
||||
@go test $(GOFLAGS) .
|
||||
@go test $(GOFLAGS) github.com/minio/minio/cmd...
|
||||
@go test $(GOFLAGS) github.com/minio/minio/pkg...
|
||||
@echo "Running all minio testing:"
|
||||
@GO15VENDOREXPERIMENT=1 go test $(GOFLAGS) github.com/minio/minio/cmd...
|
||||
@GO15VENDOREXPERIMENT=1 go test $(GOFLAGS) github.com/minio/minio/pkg...
|
||||
|
||||
coverage: build
|
||||
@echo "Running all coverage for minio"
|
||||
@./buildscripts/go-coverage.sh
|
||||
@echo "Running all coverage for minio:"
|
||||
@GO15VENDOREXPERIMENT=1 ./buildscripts/go-coverage.sh
|
||||
|
||||
gomake-all: build
|
||||
@echo "Installing minio at $(GOPATH)/bin/minio"
|
||||
@go build --ldflags $(BUILD_LDFLAGS) -o $(GOPATH)/bin/minio
|
||||
@echo "Installing minio:"
|
||||
@GO15VENDOREXPERIMENT=1 go build --ldflags $(BUILD_LDFLAGS) -o $(GOPATH)/bin/minio
|
||||
|
||||
pkg-add:
|
||||
@echo "Adding new package $(PKG)"
|
||||
@${GOPATH}/bin/govendor add $(PKG)
|
||||
@GO15VENDOREXPERIMENT=1 ${GOPATH}/bin/govendor add $(PKG)
|
||||
|
||||
pkg-update:
|
||||
@echo "Updating new package $(PKG)"
|
||||
@${GOPATH}/bin/govendor update $(PKG)
|
||||
@GO15VENDOREXPERIMENT=1 ${GOPATH}/bin/govendor update $(PKG)
|
||||
|
||||
pkg-remove:
|
||||
@echo "Remove new package $(PKG)"
|
||||
@${GOPATH}/bin/govendor remove $(PKG)
|
||||
@GO15VENDOREXPERIMENT=1 ${GOPATH}/bin/govendor remove $(PKG)
|
||||
|
||||
pkg-list:
|
||||
@$(GOPATH)/bin/govendor list
|
||||
@GO15VENDOREXPERIMENT=1 $(GOPATH)/bin/govendor list
|
||||
|
||||
install: gomake-all
|
||||
|
||||
@@ -142,7 +138,7 @@ experimental: verifiers
|
||||
@MINIO_RELEASE=EXPERIMENTAL ./buildscripts/build.sh
|
||||
|
||||
clean:
|
||||
@echo "Cleaning up all the generated files"
|
||||
@echo "Cleaning up all the generated files:"
|
||||
@find . -name '*.test' | xargs rm -fv
|
||||
@rm -rf build
|
||||
@rm -rf release
|
||||
|
||||
@@ -1,122 +1,201 @@
|
||||
# Minio Quickstart Guide [](https://slack.minio.io) [](https://goreportcard.com/report/minio/minio) [](https://hub.docker.com/r/minio/minio/) [](https://codecov.io/gh/minio/minio)
|
||||
# Minio Quickstart Guide [](https://gitter.im/minio/minio?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://goreportcard.com/report/minio/minio) [](https://codecov.io/gh/minio/minio)
|
||||
|
||||
Minio is an object storage server released under Apache License v2.0. It is compatible with Amazon S3 cloud storage service. It is best suited for storing unstructured data such as photos, videos, log files, backups and container / VM images. Size of an object can range from a few KBs to a maximum of 5TB.
|
||||
|
||||
## 1. Download
|
||||
|
||||
Minio server is light enough to be bundled with the application stack, similar to NodeJS, Redis and MySQL.
|
||||
|
||||
## Docker Container
|
||||
### Stable
|
||||
```
|
||||
docker pull minio/minio
|
||||
docker run -p 9000:9000 minio/minio server /export
|
||||
```
|
||||
| Platform| Architecture | URL|
|
||||
| ----------| -------- | ------|
|
||||
|GNU/Linux|64-bit Intel|https://dl.minio.io/server/minio/release/linux-amd64/minio|
|
||||
||32-bit Intel|https://dl.minio.io/server/minio/release/linux-386/minio|
|
||||
||32-bit ARM|https://dl.minio.io/server/minio/release/linux-arm/minio|
|
||||
|Apple OS X|64-bit Intel|https://dl.minio.io/server/minio/release/darwin-amd64/minio|
|
||||
|Microsoft Windows|64-bit|https://dl.minio.io/server/minio/release/windows-amd64/minio.exe|
|
||||
||32-bit|https://dl.minio.io/server/minio/release/windows-386/minio.exe|
|
||||
|FreeBSD|64-bit|https://dl.minio.io/server/minio/release/freebsd-amd64/minio|
|
||||
|
||||
### Edge
|
||||
```
|
||||
docker pull minio/minio:edge
|
||||
docker run -p 9000:9000 minio/minio:edge server /export
|
||||
```
|
||||
Please visit Minio Docker quickstart guide for more [here](https://docs.minio.io/docs/minio-docker-quickstart-guide)
|
||||
### Install from Homebrew
|
||||
|
||||
## macOS
|
||||
### Homebrew
|
||||
Install minio packages using [Homebrew](http://brew.sh/)
|
||||
|
||||
|
||||
```sh
|
||||
brew install minio/stable/minio
|
||||
minio server ~/Photos
|
||||
```
|
||||
#### Note
|
||||
If you previously installed minio using `brew install minio` then uninstall minio as shown below
|
||||
|
||||
```
|
||||
brew uninstall minio
|
||||
$ brew install minio
|
||||
$ minio --help
|
||||
```
|
||||
|
||||
Then re-install the latest minio using:
|
||||
|
||||
```
|
||||
brew install minio/stable/minio
|
||||
```
|
||||
|
||||
>`brew install minio` and `brew upgrade minio` will no longer install/upgrade the latest minio binaries on macOS. Upstream bugs in golang 1.8 broke Minio brew installer. Use the updated `minio/stable/minio` in your brew paths.
|
||||
|
||||
### Binary Download
|
||||
| Platform| Architecture | URL|
|
||||
| ----------| -------- | ------|
|
||||
|Apple macOS|64-bit Intel|https://dl.minio.io/server/minio/release/darwin-amd64/minio |
|
||||
```sh
|
||||
chmod 755 minio
|
||||
./minio server ~/Photos
|
||||
```
|
||||
|
||||
## GNU/Linux
|
||||
### Binary Download
|
||||
| Platform| Architecture | URL|
|
||||
| ----------| -------- | ------|
|
||||
|GNU/Linux|64-bit Intel|https://dl.minio.io/server/minio/release/linux-amd64/minio |
|
||||
| |32-bit Intel|https://dl.minio.io/server/minio/release/linux-386/minio |
|
||||
| |32-bit ARM|https://dl.minio.io/server/minio/release/linux-arm/minio |
|
||||
| |64-bit ARM|https://dl.minio.io/server/minio/release/linux-arm64/minio |
|
||||
| |32-bit ARMv6|https://dl.minio.io/server/minio/release/linux-arm6vl/minio |
|
||||
```sh
|
||||
chmod +x minio
|
||||
./minio server ~/Photos
|
||||
```
|
||||
|
||||
## Microsoft Windows
|
||||
### Binary Download
|
||||
| Platform| Architecture | URL|
|
||||
| ----------| -------- | ------|
|
||||
|Microsoft Windows|64-bit|https://dl.minio.io/server/minio/release/windows-amd64/minio.exe |
|
||||
| |32-bit|https://dl.minio.io/server/minio/release/windows-386/minio.exe |
|
||||
```sh
|
||||
minio.exe server D:\Photos
|
||||
```
|
||||
|
||||
## FreeBSD
|
||||
### Port
|
||||
Install minio packages using [pkg](https://github.com/freebsd/pkg)
|
||||
|
||||
```sh
|
||||
pkg install minio
|
||||
sysrc minio_enable=yes
|
||||
sysrc minio_disks=/home/user/Photos
|
||||
service minio start
|
||||
```
|
||||
|
||||
### Binary Download
|
||||
| Platform| Architecture | URL|
|
||||
| ----------| -------- | ------|
|
||||
|FreeBSD|64-bit|https://dl.minio.io/server/minio/release/freebsd-amd64/minio |
|
||||
```sh
|
||||
chmod 755 minio
|
||||
./minio server ~/Photos
|
||||
```
|
||||
|
||||
## Install from Source
|
||||
### Install from Source
|
||||
|
||||
Source installation is only intended for developers and advanced users. If you do not have a working Golang environment, please follow [How to install Golang](https://docs.minio.io/docs/how-to-install-golang).
|
||||
|
||||
|
||||
```sh
|
||||
go get -u github.com/minio/minio
|
||||
|
||||
$ go get -u github.com/minio/minio
|
||||
|
||||
|
||||
```
|
||||
|
||||
## Test using Minio Browser
|
||||
Minio Server comes with an embedded web based object browser. Point your web browser to http://127.0.0.1:9000 ensure your server has started successfully.
|
||||
## 2. Run Minio Server
|
||||
|
||||
|
||||
### GNU/Linux
|
||||
|
||||
```sh
|
||||
|
||||
$ chmod +x minio
|
||||
$ ./minio --help
|
||||
$ ./minio server ~/Photos
|
||||
|
||||
Endpoint: http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
AccessKey: USWUXHGYZQYFYFFIT3RE
|
||||
SecretKey: MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
Region: us-east-1
|
||||
|
||||
Browser Access:
|
||||
http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
|
||||
Command-line Access: https://docs.minio.io/docs/minio-client-quickstart-guide
|
||||
$ mc config host add myminio http://10.0.0.10:9000 USWUXHGYZQYFYFFIT3RE MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
|
||||
Object API (Amazon S3 compatible):
|
||||
Go: https://docs.minio.io/docs/golang-client-quickstart-guide
|
||||
Java: https://docs.minio.io/docs/java-client-quickstart-guide
|
||||
Python: https://docs.minio.io/docs/python-client-quickstart-guide
|
||||
JavaScript: https://docs.minio.io/docs/javascript-client-quickstart-guide
|
||||
|
||||
```
|
||||
|
||||
### OS X
|
||||
|
||||
|
||||
```sh
|
||||
|
||||
$ chmod 755 minio
|
||||
$ ./minio --help
|
||||
$ ./minio server ~/Photos
|
||||
|
||||
Endpoint: http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
AccessKey: USWUXHGYZQYFYFFIT3RE
|
||||
SecretKey: MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
Region: us-east-1
|
||||
|
||||
Browser Access:
|
||||
http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
|
||||
Command-line Access: https://docs.minio.io/docs/minio-client-quickstart-guide
|
||||
$ mc config host add myminio http://10.0.0.10:9000 USWUXHGYZQYFYFFIT3RE MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
|
||||
Object API (Amazon S3 compatible):
|
||||
Go: https://docs.minio.io/docs/golang-client-quickstart-guide
|
||||
Java: https://docs.minio.io/docs/java-client-quickstart-guide
|
||||
Python: https://docs.minio.io/docs/python-client-quickstart-guide
|
||||
JavaScript: https://docs.minio.io/docs/javascript-client-quickstart-guide
|
||||
|
||||
```
|
||||
|
||||
### Microsoft Windows
|
||||
|
||||
```sh
|
||||
|
||||
C:\Users\Username\Downloads> minio.exe --help
|
||||
C:\Users\Username\Downloads> minio.exe server D:\Photos
|
||||
|
||||
Endpoint: http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
AccessKey: USWUXHGYZQYFYFFIT3RE
|
||||
SecretKey: MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
Region: us-east-1
|
||||
|
||||
Browser Access:
|
||||
http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
|
||||
Command-line Access: https://docs.minio.io/docs/minio-client-quickstart-guide
|
||||
$ mc.exe config host add myminio http://10.0.0.10:9000 USWUXHGYZQYFYFFIT3RE MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
|
||||
Object API (Amazon S3 compatible):
|
||||
Go: https://docs.minio.io/docs/golang-client-quickstart-guide
|
||||
Java: https://docs.minio.io/docs/java-client-quickstart-guide
|
||||
Python: https://docs.minio.io/docs/python-client-quickstart-guide
|
||||
JavaScript: https://docs.minio.io/docs/javascript-client-quickstart-guide
|
||||
|
||||
|
||||
```
|
||||
|
||||
### Docker Container
|
||||
|
||||
```sh
|
||||
|
||||
$ docker pull minio/minio
|
||||
$ docker run -p 9000:9000 minio/minio
|
||||
|
||||
```
|
||||
Please visit Minio Docker quickstart guide for more [here](https://docs.minio.io/docs/minio-docker-quickstart-guide)
|
||||
|
||||
### FreeBSD
|
||||
|
||||
```sh
|
||||
|
||||
$ chmod 755 minio
|
||||
$ ./minio --help
|
||||
$ ./minio server ~/Photos
|
||||
|
||||
Endpoint: http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
AccessKey: USWUXHGYZQYFYFFIT3RE
|
||||
SecretKey: MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
Region: us-east-1
|
||||
|
||||
Browser Access:
|
||||
http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
|
||||
Command-line Access: https://docs.minio.io/docs/minio-client-quickstart-guide
|
||||
$ mc config host add myminio http://10.0.0.10:9000 USWUXHGYZQYFYFFIT3RE MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
|
||||
Object API (Amazon S3 compatible):
|
||||
Go: https://docs.minio.io/docs/golang-client-quickstart-guide
|
||||
Java: https://docs.minio.io/docs/java-client-quickstart-guide
|
||||
Python: https://docs.minio.io/docs/python-client-quickstart-guide
|
||||
JavaScript: https://docs.minio.io/docs/javascript-client-quickstart-guide
|
||||
|
||||
|
||||
```
|
||||
Please visit official zfs FreeBSD guide for more details [here](https://www.freebsd.org/doc/handbook/zfs-quickstart.html)
|
||||
|
||||
## 3. Test Minio Server using Minio Browser
|
||||
|
||||
Open a web browser and navigate to http://127.0.0.1:9000 to view your buckets on minio server.
|
||||
|
||||

|
||||
|
||||
## Test using Minio Client `mc`
|
||||
`mc` provides a modern alternative to UNIX commands like ls, cat, cp, mirror, diff etc. It supports filesystems and Amazon S3 compatible cloud storage services. Follow the Minio Client [Quickstart Guide](https://docs.minio.io/docs/minio-client-quickstart-guide) for further instructions.
|
||||
|
||||
## Explore Further
|
||||
## 4. Test Minio Server using `mc`
|
||||
|
||||
|
||||
Install mc from [here](https://docs.minio.io/docs/minio-client-quickstart-guide). Use `mc ls` command to list all the buckets on your minio server.
|
||||
|
||||
```sh
|
||||
|
||||
$ mc ls myminio/
|
||||
[2015-08-05 08:13:22 IST] 0B andoria/
|
||||
[2015-08-05 06:14:26 IST] 0B deflector/
|
||||
[2015-08-05 08:13:11 IST] 0B ferenginar/
|
||||
[2016-03-08 14:56:35 IST] 0B jarjarbing/
|
||||
[2016-01-20 16:07:41 IST] 0B my.minio.io/
|
||||
|
||||
```
|
||||
|
||||
For more examples please navigate to [Minio Client Complete Guide](https://docs.minio.io/docs/minio-client-complete-guide).
|
||||
|
||||
|
||||
## 5. Explore Further
|
||||
|
||||
- [Minio Erasure Code QuickStart Guide](https://docs.minio.io/docs/minio-erasure-code-quickstart-guide)
|
||||
- [Minio Docker Quickstart Guide](https://docs.minio.io/docs/minio-docker-quickstart-guide)
|
||||
- [Use `mc` with Minio Server](https://docs.minio.io/docs/minio-client-quickstart-guide)
|
||||
- [Use `aws-cli` with Minio Server](https://docs.minio.io/docs/aws-cli-with-minio)
|
||||
- [Use `s3cmd` with Minio Server](https://docs.minio.io/docs/s3cmd-with-minio)
|
||||
- [Use `minio-go` SDK with Minio Server](https://docs.minio.io/docs/golang-client-quickstart-guide)
|
||||
- [The Minio documentation website](https://docs.minio.io)
|
||||
|
||||
## Contribute to Minio Project
|
||||
|
||||
## 6. Contribute to Minio Project
|
||||
Please follow Minio [Contributor's Guide](https://github.com/minio/minio/blob/master/CONTRIBUTING.md)
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
# Minio 快速入门 [](https://slack.minio.io) [](https://goreportcard.com/report/minio/minio) [](https://codecov.io/gh/minio/minio)
|
||||
|
||||
Minio是一个对象存储服务,基于Apache License v2.0协议. 它完全兼容亚马逊的S3云储存服务,非常适合于存储很多非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。
|
||||
|
||||
## 1. 下载
|
||||
|
||||
Minio是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL.
|
||||
|
||||
| Platform| Architecture | URL|
|
||||
| ----------| -------- | ------|
|
||||
|GNU/Linux|64-bit Intel|https://dl.minio.io/server/minio/release/linux-amd64/minio|
|
||||
||32-bit Intel|https://dl.minio.io/server/minio/release/linux-386/minio|
|
||||
||32-bit ARM|https://dl.minio.io/server/minio/release/linux-arm/minio|
|
||||
||64-bit ARM|https://dl.minio.io/server/minio/release/linux-arm64/minio|
|
||||
||32-bit ARMv6|https://dl.minio.io/server/minio/release/linux-arm6vl/minio|
|
||||
|Apple OS X|64-bit Intel|https://dl.minio.io/server/minio/release/darwin-amd64/minio|
|
||||
|Microsoft Windows|64-bit|https://dl.minio.io/server/minio/release/windows-amd64/minio.exe|
|
||||
||32-bit|https://dl.minio.io/server/minio/release/windows-386/minio.exe|
|
||||
|FreeBSD|64-bit|https://dl.minio.io/server/minio/release/freebsd-amd64/minio|
|
||||
|
||||
### Homebrew 安装
|
||||
|
||||
使用[Homebrew](http://brew.sh/) 来安装minio
|
||||
|
||||
```sh
|
||||
$ brew install minio
|
||||
$ minio --help
|
||||
```
|
||||
|
||||
### 源码安装
|
||||
|
||||
源码安装只针对开发者和一些高级用户,如果你还没有golang的环境,请安装golang官网安装[How to install Golang](https://docs.minio.io/docs/zh-CN/how-to-install-golang).
|
||||
|
||||
```sh
|
||||
|
||||
$ go get -u github.com/minio/minio
|
||||
|
||||
|
||||
```
|
||||
|
||||
## 2. 运行Minio服务
|
||||
|
||||
|
||||
### GNU/Linux
|
||||
|
||||
```sh
|
||||
|
||||
$ chmod +x minio
|
||||
$ ./minio --help
|
||||
$ ./minio server ~/Photos
|
||||
|
||||
端点: http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
AccessKey: USWUXHGYZQYFYFFIT3RE
|
||||
SecretKey: MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
区域: us-east-1
|
||||
|
||||
浏览器访问入口:
|
||||
http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
|
||||
命令行访问: https://docs.minio.io/docs/zh-CN/minio-client-quickstart-guide
|
||||
$ mc config host add myminio http://10.0.0.10:9000 USWUXHGYZQYFYFFIT3RE MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
|
||||
对象操作API (兼容Amazon S3):
|
||||
Go: https://docs.minio.io/docs/zh-CN/golang-client-quickstart-guide
|
||||
Java: https://docs.minio.io/docs/zh-CN/java-client-quickstart-guide
|
||||
Python: https://docs.minio.io/docs/zh-CN/python-client-quickstart-guide
|
||||
JavaScript: https://docs.minio.io/docs/zh-CN/javascript-client-quickstart-guide
|
||||
|
||||
```
|
||||
|
||||
### OS X
|
||||
|
||||
|
||||
```sh
|
||||
|
||||
$ chmod 755 minio
|
||||
$ ./minio --help
|
||||
$ ./minio server ~/Photos
|
||||
|
||||
端点: http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
AccessKey: USWUXHGYZQYFYFFIT3RE
|
||||
SecretKey: MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
区域: us-east-1
|
||||
|
||||
浏览器访问入口:
|
||||
http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
|
||||
命令行访问: https://docs.minio.io/docs/zh-CN/minio-client-quickstart-guide
|
||||
$ mc config host add myminio http://10.0.0.10:9000 USWUXHGYZQYFYFFIT3RE MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
|
||||
对象操作API (兼容Amazon S3):
|
||||
Go: https://docs.minio.io/docs/zh-CN/golang-client-quickstart-guide
|
||||
Java: https://docs.minio.io/docs/zh-CN/java-client-quickstart-guide
|
||||
Python: https://docs.minio.io/docs/zh-CN/python-client-quickstart-guide
|
||||
JavaScript: https://docs.minio.io/docs/zh-CN/javascript-client-quickstart-guide
|
||||
|
||||
```
|
||||
|
||||
### Microsoft Windows
|
||||
|
||||
```sh
|
||||
|
||||
C:\Users\Username\Downloads> minio.exe --help
|
||||
C:\Users\Username\Downloads> minio.exe server D:\Photos
|
||||
|
||||
端点: http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
AccessKey: USWUXHGYZQYFYFFIT3RE
|
||||
SecretKey: MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
区域: us-east-1
|
||||
|
||||
浏览器访问入口:
|
||||
http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
|
||||
命令行访问: https://docs.minio.io/docs/zh-CN/minio-client-quickstart-guide
|
||||
$ mc.exe config host add myminio http://10.0.0.10:9000 USWUXHGYZQYFYFFIT3RE MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
|
||||
对象操作API (兼容Amazon S3):
|
||||
Go: https://docs.minio.io/docs/zh-CN/golang-client-quickstart-guide
|
||||
Java: https://docs.minio.io/docs/zh-CN/java-client-quickstart-guide
|
||||
Python: https://docs.minio.io/docs/zh-CN/python-client-quickstart-guide
|
||||
JavaScript: https://docs.minio.io/docs/zh-CN/javascript-client-quickstart-guide
|
||||
|
||||
|
||||
```
|
||||
|
||||
### Docker
|
||||
|
||||
```sh
|
||||
|
||||
$ docker pull minio/minio
|
||||
$ docker run -p 9000:9000 minio/minio
|
||||
|
||||
```
|
||||
访问minio的docker入门指南获得更多内容 [here](https://docs.minio.io/docs/zh-CN/minio-docker-quickstart-guide)
|
||||
|
||||
### FreeBSD
|
||||
|
||||
```sh
|
||||
|
||||
$ chmod 755 minio
|
||||
$ ./minio --help
|
||||
$ ./minio server ~/Photos
|
||||
|
||||
端点: http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
AccessKey: USWUXHGYZQYFYFFIT3RE
|
||||
SecretKey: MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
区域: us-east-1
|
||||
|
||||
浏览器访问入口:
|
||||
http://10.0.0.10:9000 http://127.0.0.1:9000 http://172.17.0.1:9000
|
||||
|
||||
命令行访问: https://docs.minio.io/docs/zh-CN/minio-client-quickstart-guide
|
||||
$ mc config host add myminio http://10.0.0.10:9000 USWUXHGYZQYFYFFIT3RE MOJRH0mkL1IPauahWITSVvyDrQbEEIwljvmxdq03
|
||||
|
||||
对象操作API (兼容Amazon S3):
|
||||
Go: https://docs.minio.io/docs/zh-CN/golang-client-quickstart-guide
|
||||
Java: https://docs.minio.io/docs/zh-CN/java-client-quickstart-guide
|
||||
Python: https://docs.minio.io/docs/zh-CN/python-client-quickstart-guide
|
||||
JavaScript: https://docs.minio.io/docs/zh-CN/javascript-client-quickstart-guide
|
||||
|
||||
|
||||
```
|
||||
请访问FreeBSD的官网指南获取更多详细信息[here](https://www.freebsd.org/doc/handbook/zfs-quickstart.html)
|
||||
|
||||
## 3. 使用浏览器测试minio服务
|
||||
|
||||
打开浏览器并输入 http://127.0.0.1:9000 查看在minio服务器上面的所有bucket
|
||||
|
||||

|
||||
|
||||
|
||||
## 4. 使用`mc`测试minio服务
|
||||
|
||||
|
||||
按照 [这个](https://docs.minio.io/docs/minio-client-quickstart-guide) 安装mc. 使用 `mc ls` 命令显示所有在minio服务上面的bucket.
|
||||
|
||||
```sh
|
||||
|
||||
$ mc ls myminio/
|
||||
[2015-08-05 08:13:22 IST] 0B andoria/
|
||||
[2015-08-05 06:14:26 IST] 0B deflector/
|
||||
[2015-08-05 08:13:11 IST] 0B ferenginar/
|
||||
[2016-03-08 14:56:35 IST] 0B jarjarbing/
|
||||
[2016-01-20 16:07:41 IST] 0B my.minio.io/
|
||||
|
||||
```
|
||||
|
||||
查看更多的例子请访问 [Minio Client Complete Guide](https://docs.minio.io/docs/zh-CN/minio-client-complete-guide).
|
||||
|
||||
|
||||
## 5. 更多内容
|
||||
|
||||
- [Minio Erasure Code 快速入门](https://docs.minio.io/docs/zh-CN/minio-erasure-code-quickstart-guide)
|
||||
- [Minio Docker 快速入门](https://docs.minio.io/docs/zh-CN/minio-docker-quickstart-guide)
|
||||
- [使用`mc`测试 Minio Server](https://docs.minio.io/docs/zh-CN/minio-client-quickstart-guide)
|
||||
- [使用 `aws-cli` 测试 Minio Server](https://docs.minio.io/docs/zh-CN/aws-cli-with-minio)
|
||||
- [使用 `s3cmd` 测试 Minio Server](https://docs.minio.io/docs/zh-CN/s3cmd-with-minio)
|
||||
- [使用 `minio-go` SDK ce's测试 Minio Server](https://docs.minio.io/docs/zh-CN/golang-client-quickstart-guide)
|
||||
|
||||
|
||||
## 6. 给Minio项目贡献
|
||||
请按照Minio [贡献者指导手册](https://github.com/minio/minio/blob/master/CONTRIBUTING.md)
|
||||
@@ -11,12 +11,12 @@ clone_folder: c:\gopath\src\github.com\minio\minio
|
||||
|
||||
# Environment variables
|
||||
environment:
|
||||
GOROOT: c:\go17
|
||||
GOPATH: c:\gopath
|
||||
GO15VENDOREXPERIMENT: 1
|
||||
|
||||
# scripts that run after cloning repository
|
||||
install:
|
||||
- set PATH=%GOPATH%\bin;c:\go17\bin;%PATH%
|
||||
- set PATH=%GOPATH%\bin;c:\go\bin;%PATH%
|
||||
- go version
|
||||
- go env
|
||||
- python --version
|
||||
@@ -36,9 +36,9 @@ test_script:
|
||||
# Unit tests
|
||||
- ps: Add-AppveyorTest "Unit Tests" -Outcome Running
|
||||
- mkdir build\coverage
|
||||
- go test -v -timeout 17m -race github.com/minio/minio/cmd...
|
||||
- go test -v -race github.com/minio/minio/pkg...
|
||||
- go test -v -coverprofile=build\coverage\coverage.txt -covermode=atomic github.com/minio/minio/cmd
|
||||
- go test -race github.com/minio/minio/cmd...
|
||||
- go test -race github.com/minio/minio/pkg...
|
||||
- go test -coverprofile=build\coverage\coverage.txt -covermode=atomic github.com/minio/minio/cmd
|
||||
- ps: Update-AppveyorTest "Unit Tests" -Outcome Passed
|
||||
|
||||
after_test:
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
"es2015",
|
||||
"react"
|
||||
],
|
||||
"plugins": [
|
||||
"transform-object-rest-spread"
|
||||
]
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
# editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.json]
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"plugins": [
|
||||
"esformatter-jsx"
|
||||
],
|
||||
// Copied from https://github.com/royriojas/esformatter-jsx
|
||||
"jsx": {
|
||||
"formatJSX": true, //Duh! that's the default
|
||||
"attrsOnSameLineAsTag": false, // move each attribute to its own line
|
||||
"maxAttrsOnTag": 3, // if lower or equal than 3 attributes, they will be kept on a single line
|
||||
"firstAttributeOnSameLine": true, // keep the first attribute in the same line as the tag
|
||||
"formatJSXExpressions": true, // default true, if false jsxExpressions won't be recursively formatted
|
||||
"JSXExpressionsSingleLine": true, // default true, if false the JSXExpressions might span several lines
|
||||
"alignWithFirstAttribute": false, // do not align attributes with the first tag
|
||||
"spaceInJSXExpressionContainers": " ", // default to one space. Make it empty if you don't like spaces between JSXExpressionContainers
|
||||
"removeSpaceBeforeClosingJSX": false, // default false. if true <React.Something /> => <React.Something/>
|
||||
"closingTagOnNewLine": false, // default false. if true attributes on multiple lines will close the tag on a new line
|
||||
"JSXAttributeQuotes": "", // possible values "single" or "double". Leave it as empty string if you don't want to modify the attributes' quotes
|
||||
"htmlOptions": {
|
||||
// put here the options for js-beautify.html
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
**/*.swp
|
||||
cover.out
|
||||
*~
|
||||
minio
|
||||
!*/
|
||||
site/
|
||||
**/*.test
|
||||
**/*.sublime-workspace
|
||||
/.idea/
|
||||
/Minio.iml
|
||||
**/access.log
|
||||
build
|
||||
vendor/**/*.js
|
||||
vendor/**/*.json
|
||||
release
|
||||
.DS_Store
|
||||
*.syso
|
||||
coverage.txt
|
||||
node_modules
|
||||
production
|
||||
@@ -1,72 +0,0 @@
|
||||
# Minio File Browser
|
||||
|
||||
``Minio Browser`` provides minimal set of UI to manage buckets and objects on ``minio`` server. ``Minio Browser`` is written in javascript and released under [Apache 2.0 License](./LICENSE).
|
||||
|
||||
## Installation
|
||||
|
||||
### Install yarn
|
||||
```sh
|
||||
curl -o- -L https://yarnpkg.com/install.sh | bash
|
||||
yarn
|
||||
```
|
||||
|
||||
### Install `go-bindata` and `go-bindata-assetfs`
|
||||
|
||||
If you do not have a working Golang environment, please follow [Install Golang](https://docs.minio.io/docs/how-to-install-golang)
|
||||
|
||||
```sh
|
||||
go get github.com/jteeuwen/go-bindata/...
|
||||
go get github.com/elazarl/go-bindata-assetfs/...
|
||||
```
|
||||
|
||||
## Generating Assets
|
||||
|
||||
### Generate ui-assets.go
|
||||
|
||||
```sh
|
||||
yarn release
|
||||
```
|
||||
|
||||
This generates ui-assets.go in the current directory. Now do `make` in the parent directory to build the minio binary with the newly generated ``ui-assets.go``
|
||||
|
||||
### Run Minio Browser with live reload
|
||||
|
||||
```sh
|
||||
yarn dev
|
||||
```
|
||||
|
||||
Open [http://localhost:8080/minio/](http://localhost:8080/minio/) in your browser to play with the application
|
||||
|
||||
### Run Minio Browser with live reload on custom port
|
||||
|
||||
Edit `browser/webpack.config.js`
|
||||
|
||||
```diff
|
||||
diff --git a/browser/webpack.config.js b/browser/webpack.config.js
|
||||
index 3ccdaba..9496c56 100644
|
||||
--- a/browser/webpack.config.js
|
||||
+++ b/browser/webpack.config.js
|
||||
@@ -58,6 +58,7 @@ var exports = {
|
||||
historyApiFallback: {
|
||||
index: '/minio/'
|
||||
},
|
||||
+ port: 8888,
|
||||
proxy: {
|
||||
'/minio/webrpc': {
|
||||
target: 'http://localhost:9000',
|
||||
@@ -97,7 +98,7 @@ var exports = {
|
||||
if (process.env.NODE_ENV === 'dev') {
|
||||
exports.entry = [
|
||||
'webpack/hot/dev-server',
|
||||
- 'webpack-dev-server/client?http://localhost:8080',
|
||||
+ 'webpack-dev-server/client?http://localhost:8888',
|
||||
path.resolve(__dirname, 'app/index.js')
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
```sh
|
||||
yarn dev
|
||||
```
|
||||
|
||||
Open [http://localhost:8888/minio/](http://localhost:8888/minio/) in your browser to play with the application
|
||||
@@ -1,98 +0,0 @@
|
||||
.page-load {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: #32393F;
|
||||
z-index: 100;
|
||||
transition: opacity 200ms;
|
||||
-webkit-transition: opacity 200ms;
|
||||
}
|
||||
|
||||
.pl-0{
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.pl-1 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.pl-inner {
|
||||
position: absolute;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
left: 50%;
|
||||
margin-left: -50px;
|
||||
top: 50%;
|
||||
margin-top: -50px;
|
||||
text-align: center;
|
||||
-webkit-animation: fade-in 500ms;
|
||||
animation: fade-in 500ms;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
animation-delay: 350ms;
|
||||
-webkit-animation-delay: 350ms;
|
||||
-webkit-backface-visibility: visible;
|
||||
backface-visibility: visible;
|
||||
}
|
||||
|
||||
.pl-inner:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
display: block;
|
||||
-webkit-animation: spin 1000ms infinite linear;
|
||||
animation: spin 1000ms infinite linear;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);;
|
||||
border-left-color: #fff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.pl-inner > img {
|
||||
width: 30px;
|
||||
margin-top: 28px;
|
||||
}
|
||||
|
||||
@-webkit-keyframes fade-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" viewBox="139.0389584668397 284.78404581828653 12.617622649141168 6.417622649141265"><defs><path d="M139.04 290.7L144.95 284.78L145.46 285.29L139.54 291.2L139.04 290.7Z" id="NsdmgIWbGe"></path><path d="M145.24 285.29L151.15 291.2L151.66 290.7L145.74 284.78L145.24 285.29Z" id="VqPWmhvQEo"></path></defs><g visibility="inherit"><g><use xlink:href="#NsdmgIWbGe" opacity="1" fill="#000000" fill-opacity="1"></use></g><g><use xlink:href="#VqPWmhvQEo" opacity="1" fill="#000000" fill-opacity="1"></use></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 797 B |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewbox="0 0 160 256"
|
||||
version="1.1"
|
||||
id="svg3092"
|
||||
height="218.14844"
|
||||
width="137">
|
||||
<defs
|
||||
id="defs3094" />
|
||||
<metadata
|
||||
id="metadata3097">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(0.99999967,-982.85149)"
|
||||
id="layer1">
|
||||
<g
|
||||
transform="matrix(1.0112586,0,0,1.0112586,5.4603732,-13.223714)"
|
||||
id="g4144">
|
||||
<g
|
||||
id="g4140">
|
||||
<g
|
||||
style="image-rendering:auto"
|
||||
id="minio"
|
||||
transform="matrix(1.0000023,0,0,0.99999799,-739.31646,295.2269)">
|
||||
<title
|
||||
id="title3337">Minio Logo</title>
|
||||
<path
|
||||
d="m 803.42903,801.80813 c 12.40802,4.17067 27.0499,9.11665 37.95186,12.80906 -12.01295,-21.20683 -27.84305,-34.11687 -37.95186,-40.78578 l 0,27.97672 z m 0,93.72113 -14.22303,8.96217 0,-92.45864 c -1.52985,-0.5139 -2.97948,-0.9981 -4.33405,-1.45259 -19.98593,-6.67189 -32.7207,-17.95703 -35.85168,-31.77904 -2.54577,-11.21386 1.55064,-23.02184 11.24654,-32.39691 8.84929,-8.55225 21.22761,-18.39964 31.17304,-26.31619 3.60329,-2.86658 6.73129,-5.3173 9.2028,-7.39669 2.31406,-1.93977 1.61598,-4.95488 0.57033,-6.21441 -1.74073,-2.09127 -4.61921,-1.74669 -6.56195,-0.32379 -0.10398,0.0802 -5.65595,4.40832 -5.65595,4.40832 l -8.58195,-11.57033 c 0,0 5.60843,-4.14096 5.8223,-4.30137 8.39777,-6.155 19.54034,-4.98758 25.92406,2.71509 3.19039,3.84093 4.68459,8.69779 4.20929,13.67051 -0.47232,4.9549 -2.84579,9.43153 -6.68078,12.5922 -2.58439,2.12988 -5.73912,4.64298 -9.39291,7.54522 -9.70779,7.72641 -21.78905,17.33915 -30.14226,25.41907 -6.1253,5.9233 -8.70671,12.67834 -7.26896,19.02345 1.9873,8.75424 11.33268,16.34105 26.32213,21.37911 l 0,-46.22486 c 40.29563,13.62298 68.76248,61.22321 78.20589,87.64039 0,0 -41.76308,-14.15768 -63.98286,-21.64051 l 0,78.7198"
|
||||
style="fill:#f8f8f8;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path48" />
|
||||
<path
|
||||
d="m 803.42903,826.12513 -14.22303,-4.78261 0,-9.30973 14.22303,4.77667 0,9.31567"
|
||||
style="fill:#cdccca;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path50" />
|
||||
<path
|
||||
d="m 734.75566,745.06155 c -0.23469,0.16636 -0.54956,0.14853 -0.73077,-0.0743 -0.17823,-0.22576 -0.13063,-0.53766 0.0802,-0.73373 4.93113,-4.51525 24.45661,-23.86844 46.30805,-45.2624 l 8.58193,11.57033 c 0,0 -53.54135,34.01288 -54.23942,34.50007"
|
||||
style="fill:#f14621;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path52" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.0 KiB |
@@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" width="16" height="4" viewBox="4 10 16 4"><defs><path d="M4 12C4 13.1 4.9 14 6 14C7.1 14 8 13.1 8 12C8 10.9 7.1 10 6 10C4.9 10 4 10.9 4 12ZM16 12C16 13.1 16.9 14 18 14C19.1 14 20 13.1 20 12C20 10.9 19.1 10 18 10C16.9 10 16 10.9 16 12ZM10 12C10 13.1 10.9 14 12 14C13.1 14 14 13.1 14 12C14 10.9 13.1 10 12 10C10.9 10 10 10.9 10 12Z" id="mccsKZxKL3"></path></defs><g visibility="visible"><g><use xlink:href="#mccsKZxKL3" opacity="1" fill="#eaeaea" fill-opacity="1"></use><g><use xlink:href="#mccsKZxKL3" opacity="1" fill-opacity="0" stroke="#000000" stroke-width="1" stroke-opacity="0"></use></g></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 894 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M6 10c-1.1 0-2 0.9-2 2s0.9 2 2 2 2-0.9 2-2-0.9-2-2-2zm12 0c-1.1 0-2 0.9-2 2s0.9 2 2 2 2-0.9 2-2-0.9-2-2-2zm-6 0c-1.1 0-2 0.9-2 2s0.9 2 2 2 2-0.9 2-2-0.9-2-2-2z"/></svg>
|
||||
|
Before Width: | Height: | Size: 261 B |
@@ -1,3 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid meet" width="9" height="9" viewBox="326.76441742035513 536.0133077721175 13 13"><defs><path d="M339.76 536.01L326.76 549.01L339.76 549.01L339.76 536.01Z" id="kt3PSf43ua"></path></defs><g visibility="visible"><g><use xlink:href="#kt3PSf43ua" opacity="1" fill="#dadada" fill-opacity="1"></use></g></g></svg>
|
||||
|
Before Width: | Height: | Size: 586 B |
@@ -1,56 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Minio Browser</title>
|
||||
<link rel="stylesheet" href="/minio/loader.css" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="page-load">
|
||||
<div class="pl-inner">
|
||||
<img src="/minio/logo.svg" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div id="root"></div>
|
||||
|
||||
<!--[if lt IE 11]>
|
||||
<div class="ie-warning">
|
||||
<div class="iw-inner">
|
||||
<i class="iwi-icon fa fa-warning"></i>
|
||||
|
||||
You are using Internet Explorer version 12.0 or lower. Due to security issues and lack of support for Web Standards it is highly recommended that you upgrade to a modern browser
|
||||
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="http://www.google.com/chrome/">
|
||||
<img src="/minio/chrome.png" alt="">
|
||||
<div>Chrome</div>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.mozilla.org/en-US/firefox/new/">
|
||||
<img src="/minio/firefox.png" alt="">
|
||||
<div>Firefox</div>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://www.apple.com/safari/">
|
||||
<img src="/minio/safari.png" alt="">
|
||||
<div>Safari</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="iwi-skip">Skip & Continue</div>
|
||||
</div>
|
||||
</div>
|
||||
<![endif]-->
|
||||
|
||||
<script>currentUiVersion = 'MINIO_UI_VERSION'</script>
|
||||
<script src="/minio/index_bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import 'babel-polyfill'
|
||||
|
||||
import './less/main.less'
|
||||
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import thunkMiddleware from 'redux-thunk'
|
||||
import createStore from 'redux/lib/createStore'
|
||||
import applyMiddleware from 'redux/lib/applyMiddleware'
|
||||
|
||||
import Route from 'react-router/lib/Route'
|
||||
import Router from 'react-router/lib/Router'
|
||||
import browserHistory from 'react-router/lib/browserHistory'
|
||||
import IndexRoute from 'react-router/lib/IndexRoute'
|
||||
|
||||
import Provider from 'react-redux/lib/components/Provider'
|
||||
import connect from 'react-redux/lib/components/connect'
|
||||
|
||||
import Moment from 'moment'
|
||||
|
||||
import { minioBrowserPrefix } from './js/constants.js'
|
||||
import * as actions from './js/actions.js'
|
||||
import reducer from './js/reducers.js'
|
||||
|
||||
import _Login from './js/components/Login.js'
|
||||
import _Browse from './js/components/Browse.js'
|
||||
import fontAwesome from 'font-awesome/css/font-awesome.css'
|
||||
|
||||
import Web from './js/web'
|
||||
window.Web = Web
|
||||
|
||||
import storage from 'local-storage-fallback'
|
||||
const store = applyMiddleware(thunkMiddleware)(createStore)(reducer)
|
||||
const Browse = connect(state => state)(_Browse)
|
||||
const Login = connect(state => state)(_Login)
|
||||
|
||||
let web = new Web(`${window.location.protocol}//${window.location.host}${minioBrowserPrefix}/webrpc`, store.dispatch)
|
||||
|
||||
window.web = web
|
||||
|
||||
store.dispatch(actions.setWeb(web))
|
||||
|
||||
function authNeeded(nextState, replace, cb) {
|
||||
if (web.LoggedIn()) {
|
||||
return cb()
|
||||
}
|
||||
if (location.pathname === minioBrowserPrefix || location.pathname === minioBrowserPrefix + '/') {
|
||||
replace(`${minioBrowserPrefix}/login`)
|
||||
}
|
||||
return cb()
|
||||
}
|
||||
|
||||
function authNotNeeded(nextState, replace) {
|
||||
if (web.LoggedIn()) {
|
||||
replace(`${minioBrowserPrefix}`)
|
||||
}
|
||||
}
|
||||
|
||||
const App = (props) => {
|
||||
return <div>
|
||||
{ props.children }
|
||||
</div>
|
||||
}
|
||||
|
||||
ReactDOM.render((
|
||||
<Provider store={ store } web={ web }>
|
||||
<Router history={ browserHistory }>
|
||||
<Route path='/' component={ App }>
|
||||
<Route path='minio' component={ App }>
|
||||
<IndexRoute component={ Browse } onEnter={ authNeeded } />
|
||||
<Route path='login' component={ Login } onEnter={ authNotNeeded } />
|
||||
<Route path=':bucket' component={ Browse } onEnter={ authNeeded } />
|
||||
<Route path=':bucket/*' component={ Browse } onEnter={ authNeeded } />
|
||||
</Route>
|
||||
</Route>
|
||||
</Router>
|
||||
</Provider>
|
||||
), document.getElementById('root'))
|
||||
|
||||
//Page loader
|
||||
let delay = [0, 400]
|
||||
let i = 0
|
||||
|
||||
function handleLoader() {
|
||||
if (i < 2) {
|
||||
setTimeout(function() {
|
||||
document.querySelector('.page-load').classList.add('pl-' + i)
|
||||
i++
|
||||
handleLoader()
|
||||
}, delay[i])
|
||||
}
|
||||
}
|
||||
handleLoader()
|
||||
|
||||
if (storage.getItem('newlyUpdated')) {
|
||||
store.dispatch(actions.showAlert({
|
||||
type: 'success',
|
||||
message: "Updated to the latest UI Version."
|
||||
}))
|
||||
storage.removeItem('newlyUpdated')
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import expect from 'expect';
|
||||
import JSONrpc from '../jsonrpc';
|
||||
|
||||
describe('jsonrpc', () => {
|
||||
it('should fail with invalid endpoint', (done) => {
|
||||
try {
|
||||
let jsonRPC = new JSONrpc({
|
||||
endpoint: 'htt://localhost:9000',
|
||||
namespace: 'Test'
|
||||
});
|
||||
} catch (e) {
|
||||
done();
|
||||
}
|
||||
});
|
||||
it('should succeed with valid endpoint', () => {
|
||||
let jsonRPC = new JSONrpc({
|
||||
endpoint: 'http://localhost:9000/webrpc',
|
||||
namespace: 'Test'
|
||||
});
|
||||
expect(jsonRPC.version).toEqual('2.0');
|
||||
expect(jsonRPC.host).toEqual('localhost');
|
||||
expect(jsonRPC.port).toEqual('9000');
|
||||
expect(jsonRPC.path).toEqual('/webrpc');
|
||||
expect(jsonRPC.scheme).toEqual('http');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,637 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Moment from 'moment'
|
||||
import browserHistory from 'react-router/lib/browserHistory'
|
||||
import storage from 'local-storage-fallback'
|
||||
import { minioBrowserPrefix } from './constants'
|
||||
|
||||
export const SET_WEB = 'SET_WEB'
|
||||
export const SET_CURRENT_BUCKET = 'SET_CURRENT_BUCKET'
|
||||
export const SET_CURRENT_PATH = 'SET_CURRENT_PATH'
|
||||
export const SET_BUCKETS = 'SET_BUCKETS'
|
||||
export const ADD_BUCKET = 'ADD_BUCKET'
|
||||
export const SET_VISIBLE_BUCKETS = 'SET_VISIBLE_BUCKETS'
|
||||
export const SET_OBJECTS = 'SET_OBJECTS'
|
||||
export const APPEND_OBJECTS = 'APPEND_OBJECTS'
|
||||
export const RESET_OBJECTS = 'RESET_OBJECTS'
|
||||
export const SET_STORAGE_INFO = 'SET_STORAGE_INFO'
|
||||
export const SET_SERVER_INFO = 'SET_SERVER_INFO'
|
||||
export const SHOW_MAKEBUCKET_MODAL = 'SHOW_MAKEBUCKET_MODAL'
|
||||
export const ADD_UPLOAD = 'ADD_UPLOAD'
|
||||
export const STOP_UPLOAD = 'STOP_UPLOAD'
|
||||
export const UPLOAD_PROGRESS = 'UPLOAD_PROGRESS'
|
||||
export const SET_ALERT = 'SET_ALERT'
|
||||
export const SET_LOGIN_ERROR = 'SET_LOGIN_ERROR'
|
||||
export const SET_SHOW_ABORT_MODAL = 'SET_SHOW_ABORT_MODAL'
|
||||
export const SHOW_ABOUT = 'SHOW_ABOUT'
|
||||
export const SET_SORT_NAME_ORDER = 'SET_SORT_NAME_ORDER'
|
||||
export const SET_SORT_SIZE_ORDER = 'SET_SORT_SIZE_ORDER'
|
||||
export const SET_SORT_DATE_ORDER = 'SET_SORT_DATE_ORDER'
|
||||
export const SET_LATEST_UI_VERSION = 'SET_LATEST_UI_VERSION'
|
||||
export const SET_SIDEBAR_STATUS = 'SET_SIDEBAR_STATUS'
|
||||
export const SET_LOGIN_REDIRECT_PATH = 'SET_LOGIN_REDIRECT_PATH'
|
||||
export const SET_LOAD_BUCKET = 'SET_LOAD_BUCKET'
|
||||
export const SET_LOAD_PATH = 'SET_LOAD_PATH'
|
||||
export const SHOW_SETTINGS = 'SHOW_SETTINGS'
|
||||
export const SET_SETTINGS = 'SET_SETTINGS'
|
||||
export const SHOW_BUCKET_POLICY = 'SHOW_BUCKET_POLICY'
|
||||
export const SET_POLICIES = 'SET_POLICIES'
|
||||
export const SET_SHARE_OBJECT = 'SET_SHARE_OBJECT'
|
||||
export const DELETE_CONFIRMATION = 'DELETE_CONFIRMATION'
|
||||
export const SET_PREFIX_WRITABLE = 'SET_PREFIX_WRITABLE'
|
||||
export const REMOVE_OBJECT = 'REMOVE_OBJECT'
|
||||
export const CHECKED_OBJECTS_ADD = 'CHECKED_OBJECTS_ADD'
|
||||
export const CHECKED_OBJECTS_REMOVE = 'CHECKED_OBJECTS_REMOVE'
|
||||
export const CHECKED_OBJECTS_RESET = 'CHECKED_OBJECTS_RESET'
|
||||
|
||||
export const showDeleteConfirmation = (object) => {
|
||||
return {
|
||||
type: DELETE_CONFIRMATION,
|
||||
payload: {
|
||||
object,
|
||||
show: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const hideDeleteConfirmation = () => {
|
||||
return {
|
||||
type: DELETE_CONFIRMATION,
|
||||
payload: {
|
||||
object: '',
|
||||
show: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const showShareObject = (object, url) => {
|
||||
return {
|
||||
type: SET_SHARE_OBJECT,
|
||||
shareObject: {
|
||||
object,
|
||||
url,
|
||||
show: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const hideShareObject = () => {
|
||||
return {
|
||||
type: SET_SHARE_OBJECT,
|
||||
shareObject: {
|
||||
url: '',
|
||||
show: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const shareObject = (object, days, hours, minutes) => (dispatch, getState) => {
|
||||
const {currentBucket, web} = getState()
|
||||
let host = location.host
|
||||
let bucket = currentBucket
|
||||
|
||||
if (!web.LoggedIn()) {
|
||||
dispatch(showShareObject(object, `${host}/${bucket}/${object}`))
|
||||
return
|
||||
}
|
||||
|
||||
let expiry = days * 24 * 60 * 60 + hours * 60 * 60 + minutes * 60
|
||||
web.PresignedGet({
|
||||
host,
|
||||
bucket,
|
||||
object,
|
||||
expiry
|
||||
})
|
||||
.then(obj => {
|
||||
dispatch(showShareObject(object, obj.url))
|
||||
dispatch(showAlert({
|
||||
type: 'success',
|
||||
message: `Object shared. Expires in ${days} days ${hours} hours ${minutes} minutes.`
|
||||
}))
|
||||
})
|
||||
.catch(err => {
|
||||
dispatch(showAlert({
|
||||
type: 'danger',
|
||||
message: err.message
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
export const setLoginRedirectPath = (path) => {
|
||||
return {
|
||||
type: SET_LOGIN_REDIRECT_PATH,
|
||||
path
|
||||
}
|
||||
}
|
||||
|
||||
export const setLoadPath = (loadPath) => {
|
||||
return {
|
||||
type: SET_LOAD_PATH,
|
||||
loadPath
|
||||
}
|
||||
}
|
||||
|
||||
export const setLoadBucket = (loadBucket) => {
|
||||
return {
|
||||
type: SET_LOAD_BUCKET,
|
||||
loadBucket
|
||||
}
|
||||
}
|
||||
|
||||
export const setWeb = web => {
|
||||
return {
|
||||
type: SET_WEB,
|
||||
web
|
||||
}
|
||||
}
|
||||
|
||||
export const setBuckets = buckets => {
|
||||
return {
|
||||
type: SET_BUCKETS,
|
||||
buckets
|
||||
}
|
||||
}
|
||||
|
||||
export const addBucket = bucket => {
|
||||
return {
|
||||
type: ADD_BUCKET,
|
||||
bucket
|
||||
}
|
||||
}
|
||||
|
||||
export const showMakeBucketModal = () => {
|
||||
return {
|
||||
type: SHOW_MAKEBUCKET_MODAL,
|
||||
showMakeBucketModal: true
|
||||
}
|
||||
}
|
||||
|
||||
export const hideAlert = () => {
|
||||
return {
|
||||
type: SET_ALERT,
|
||||
alert: {
|
||||
show: false,
|
||||
message: '',
|
||||
type: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const showAlert = alert => {
|
||||
return (dispatch, getState) => {
|
||||
let alertTimeout = null
|
||||
if (alert.type !== 'danger') {
|
||||
alertTimeout = setTimeout(() => {
|
||||
dispatch({
|
||||
type: SET_ALERT,
|
||||
alert: {
|
||||
show: false
|
||||
}
|
||||
})
|
||||
}, 5000)
|
||||
}
|
||||
dispatch({
|
||||
type: SET_ALERT,
|
||||
alert: Object.assign({}, alert, {
|
||||
show: true,
|
||||
alertTimeout
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const removeObject = object => {
|
||||
return {
|
||||
type: REMOVE_OBJECT,
|
||||
object
|
||||
}
|
||||
}
|
||||
|
||||
export const setSidebarStatus = (status) => {
|
||||
return {
|
||||
type: SET_SIDEBAR_STATUS,
|
||||
sidebarStatus: status
|
||||
}
|
||||
}
|
||||
|
||||
export const hideMakeBucketModal = () => {
|
||||
return {
|
||||
type: SHOW_MAKEBUCKET_MODAL,
|
||||
showMakeBucketModal: false
|
||||
}
|
||||
}
|
||||
|
||||
export const setVisibleBuckets = visibleBuckets => {
|
||||
return {
|
||||
type: SET_VISIBLE_BUCKETS,
|
||||
visibleBuckets
|
||||
}
|
||||
}
|
||||
|
||||
const appendObjects = (objects, marker, istruncated) => {
|
||||
return {
|
||||
type: APPEND_OBJECTS,
|
||||
objects,
|
||||
marker,
|
||||
istruncated
|
||||
}
|
||||
}
|
||||
|
||||
export const setObjects = (objects) => {
|
||||
return {
|
||||
type: SET_OBJECTS,
|
||||
objects,
|
||||
}
|
||||
}
|
||||
|
||||
export const resetObjects = () => {
|
||||
return {
|
||||
type: RESET_OBJECTS
|
||||
}
|
||||
}
|
||||
|
||||
export const setCurrentBucket = currentBucket => {
|
||||
return {
|
||||
type: SET_CURRENT_BUCKET,
|
||||
currentBucket
|
||||
}
|
||||
}
|
||||
|
||||
export const setCurrentPath = currentPath => {
|
||||
return {
|
||||
type: SET_CURRENT_PATH,
|
||||
currentPath
|
||||
}
|
||||
}
|
||||
|
||||
export const setStorageInfo = storageInfo => {
|
||||
return {
|
||||
type: SET_STORAGE_INFO,
|
||||
storageInfo
|
||||
}
|
||||
}
|
||||
|
||||
export const setServerInfo = serverInfo => {
|
||||
return {
|
||||
type: SET_SERVER_INFO,
|
||||
serverInfo
|
||||
}
|
||||
}
|
||||
|
||||
const setPrefixWritable = prefixWritable => {
|
||||
return {
|
||||
type: SET_PREFIX_WRITABLE,
|
||||
prefixWritable,
|
||||
}
|
||||
}
|
||||
|
||||
export const selectBucket = (newCurrentBucket, prefix) => {
|
||||
if (!prefix)
|
||||
prefix = ''
|
||||
return (dispatch, getState) => {
|
||||
let web = getState().web
|
||||
let currentBucket = getState().currentBucket
|
||||
|
||||
if (currentBucket !== newCurrentBucket) dispatch(setLoadBucket(newCurrentBucket))
|
||||
|
||||
dispatch(setCurrentBucket(newCurrentBucket))
|
||||
dispatch(selectPrefix(prefix))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
export const listObjects = () => {
|
||||
return (dispatch, getState) => {
|
||||
const {currentBucket, currentPath, marker, objects, istruncated, web} = getState()
|
||||
if (!istruncated) return
|
||||
web.ListObjects({
|
||||
bucketName: currentBucket,
|
||||
prefix: currentPath,
|
||||
marker: marker
|
||||
})
|
||||
.then(res => {
|
||||
let objects = res.objects
|
||||
if (!objects)
|
||||
objects = []
|
||||
objects = objects.map(object => {
|
||||
object.name = object.name.replace(`${currentPath}`, '');
|
||||
return object
|
||||
})
|
||||
dispatch(appendObjects(objects, res.nextmarker, res.istruncated))
|
||||
dispatch(setPrefixWritable(res.writable))
|
||||
dispatch(setLoadBucket(''))
|
||||
dispatch(setLoadPath(''))
|
||||
})
|
||||
.catch(err => {
|
||||
dispatch(showAlert({
|
||||
type: 'danger',
|
||||
message: err.message
|
||||
}))
|
||||
dispatch(setLoadBucket(''))
|
||||
dispatch(setLoadPath(''))
|
||||
// Use browserHistory.replace instead of push so that browser back button works fine.
|
||||
browserHistory.replace(`${minioBrowserPrefix}/login`)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const selectPrefix = prefix => {
|
||||
return (dispatch, getState) => {
|
||||
const {currentBucket, web} = getState()
|
||||
dispatch(resetObjects())
|
||||
dispatch(setLoadPath(prefix))
|
||||
web.ListObjects({
|
||||
bucketName: currentBucket,
|
||||
prefix,
|
||||
marker: ""
|
||||
})
|
||||
.then(res => {
|
||||
let objects = res.objects
|
||||
if (!objects)
|
||||
objects = []
|
||||
objects = objects.map(object => {
|
||||
object.name = object.name.replace(`${prefix}`, '');
|
||||
return object
|
||||
})
|
||||
dispatch(appendObjects(
|
||||
objects,
|
||||
res.nextmarker,
|
||||
res.istruncated
|
||||
))
|
||||
dispatch(setPrefixWritable(res.writable))
|
||||
dispatch(setSortNameOrder(false))
|
||||
dispatch(setCurrentPath(prefix))
|
||||
dispatch(setLoadBucket(''))
|
||||
dispatch(setLoadPath(''))
|
||||
})
|
||||
.catch(err => {
|
||||
dispatch(showAlert({
|
||||
type: 'danger',
|
||||
message: err.message
|
||||
}))
|
||||
dispatch(setLoadBucket(''))
|
||||
dispatch(setLoadPath(''))
|
||||
// Use browserHistory.replace instead of push so that browser back button works fine.
|
||||
browserHistory.replace(`${minioBrowserPrefix}/login`)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const addUpload = options => {
|
||||
return {
|
||||
type: ADD_UPLOAD,
|
||||
slug: options.slug,
|
||||
size: options.size,
|
||||
xhr: options.xhr,
|
||||
name: options.name
|
||||
}
|
||||
}
|
||||
|
||||
export const stopUpload = options => {
|
||||
return {
|
||||
type: STOP_UPLOAD,
|
||||
slug: options.slug
|
||||
}
|
||||
}
|
||||
|
||||
export const uploadProgress = options => {
|
||||
return {
|
||||
type: UPLOAD_PROGRESS,
|
||||
slug: options.slug,
|
||||
loaded: options.loaded
|
||||
}
|
||||
}
|
||||
|
||||
export const setShowAbortModal = showAbortModal => {
|
||||
return {
|
||||
type: SET_SHOW_ABORT_MODAL,
|
||||
showAbortModal
|
||||
}
|
||||
}
|
||||
|
||||
export const setLoginError = () => {
|
||||
return {
|
||||
type: SET_LOGIN_ERROR,
|
||||
loginError: true
|
||||
}
|
||||
}
|
||||
|
||||
export const downloadSelected = (url, req, xhr) => {
|
||||
return (dispatch) => {
|
||||
var anchor = document.createElement('a')
|
||||
document.body.appendChild(anchor);
|
||||
xhr.open('POST', url, true)
|
||||
xhr.responseType = 'blob'
|
||||
|
||||
xhr.onload = function(e) {
|
||||
if (this.status == 200) {
|
||||
dispatch(checkedObjectsReset())
|
||||
var blob = new Blob([this.response], {
|
||||
type: 'octet/stream'
|
||||
})
|
||||
var blobUrl = window.URL.createObjectURL(blob);
|
||||
var separator = req.prefix.length > 1 ? '-' : ''
|
||||
|
||||
anchor.href = blobUrl
|
||||
anchor.download = req.bucketName+separator+req.prefix.slice(0, -1)+'.zip';
|
||||
|
||||
|
||||
|
||||
|
||||
anchor.click()
|
||||
window.URL.revokeObjectURL(blobUrl)
|
||||
anchor.remove()
|
||||
}
|
||||
};
|
||||
xhr.send(JSON.stringify(req));
|
||||
}
|
||||
}
|
||||
|
||||
export const uploadFile = (file, xhr) => {
|
||||
return (dispatch, getState) => {
|
||||
const {currentBucket, currentPath} = getState()
|
||||
const objectName = `${currentPath}${file.name}`
|
||||
const uploadUrl = `${window.location.origin}/minio/upload/${currentBucket}/${objectName}`
|
||||
// The slug is a unique identifer for the file upload.
|
||||
const slug = `${currentBucket}-${currentPath}-${file.name}`
|
||||
|
||||
xhr.open('PUT', uploadUrl, true)
|
||||
xhr.withCredentials = false
|
||||
const token = storage.getItem('token')
|
||||
if (token) xhr.setRequestHeader("Authorization", 'Bearer ' + storage.getItem('token'))
|
||||
xhr.setRequestHeader('x-amz-date', Moment().utc().format('YYYYMMDDTHHmmss') + 'Z')
|
||||
dispatch(addUpload({
|
||||
slug,
|
||||
xhr,
|
||||
size: file.size,
|
||||
name: file.name
|
||||
}))
|
||||
|
||||
xhr.onload = function(event) {
|
||||
if (xhr.status == 401 || xhr.status == 403 || xhr.status == 500) {
|
||||
setShowAbortModal(false)
|
||||
dispatch(stopUpload({
|
||||
slug
|
||||
}))
|
||||
dispatch(showAlert({
|
||||
type: 'danger',
|
||||
message: 'Unauthorized request.'
|
||||
}))
|
||||
}
|
||||
if (xhr.status == 200) {
|
||||
setShowAbortModal(false)
|
||||
dispatch(stopUpload({
|
||||
slug
|
||||
}))
|
||||
dispatch(showAlert({
|
||||
type: 'success',
|
||||
message: 'File \'' + file.name + '\' uploaded successfully.'
|
||||
}))
|
||||
dispatch(selectPrefix(currentPath))
|
||||
}
|
||||
}
|
||||
|
||||
xhr.upload.addEventListener('error', event => {
|
||||
dispatch(showAlert({
|
||||
type: 'danger',
|
||||
message: 'Error occurred uploading \'' + file.name + '\'.'
|
||||
}))
|
||||
dispatch(stopUpload({
|
||||
slug
|
||||
}))
|
||||
})
|
||||
|
||||
xhr.upload.addEventListener('progress', event => {
|
||||
if (event.lengthComputable) {
|
||||
let loaded = event.loaded
|
||||
let total = event.total
|
||||
|
||||
// Update the counter.
|
||||
dispatch(uploadProgress({
|
||||
slug,
|
||||
loaded
|
||||
}))
|
||||
}
|
||||
})
|
||||
xhr.send(file)
|
||||
}
|
||||
}
|
||||
|
||||
export const showAbout = () => {
|
||||
return {
|
||||
type: SHOW_ABOUT,
|
||||
showAbout: true
|
||||
}
|
||||
}
|
||||
|
||||
export const hideAbout = () => {
|
||||
return {
|
||||
type: SHOW_ABOUT,
|
||||
showAbout: false
|
||||
}
|
||||
}
|
||||
|
||||
export const setSortNameOrder = (sortNameOrder) => {
|
||||
return {
|
||||
type: SET_SORT_NAME_ORDER,
|
||||
sortNameOrder
|
||||
}
|
||||
}
|
||||
|
||||
export const setSortSizeOrder = (sortSizeOrder) => {
|
||||
return {
|
||||
type: SET_SORT_SIZE_ORDER,
|
||||
sortSizeOrder
|
||||
}
|
||||
}
|
||||
|
||||
export const setSortDateOrder = (sortDateOrder) => {
|
||||
return {
|
||||
type: SET_SORT_DATE_ORDER,
|
||||
sortDateOrder
|
||||
}
|
||||
}
|
||||
|
||||
export const setLatestUIVersion = (latestUiVersion) => {
|
||||
return {
|
||||
type: SET_LATEST_UI_VERSION,
|
||||
latestUiVersion
|
||||
}
|
||||
}
|
||||
|
||||
export const showSettings = () => {
|
||||
return {
|
||||
type: SHOW_SETTINGS,
|
||||
showSettings: true
|
||||
}
|
||||
}
|
||||
|
||||
export const hideSettings = () => {
|
||||
return {
|
||||
type: SHOW_SETTINGS,
|
||||
showSettings: false
|
||||
}
|
||||
}
|
||||
|
||||
export const setSettings = (settings) => {
|
||||
return {
|
||||
type: SET_SETTINGS,
|
||||
settings
|
||||
}
|
||||
}
|
||||
|
||||
export const showBucketPolicy = () => {
|
||||
return {
|
||||
type: SHOW_BUCKET_POLICY,
|
||||
showBucketPolicy: true
|
||||
}
|
||||
}
|
||||
|
||||
export const hideBucketPolicy = () => {
|
||||
return {
|
||||
type: SHOW_BUCKET_POLICY,
|
||||
showBucketPolicy: false
|
||||
}
|
||||
}
|
||||
|
||||
export const setPolicies = (policies) => {
|
||||
return {
|
||||
type: SET_POLICIES,
|
||||
policies
|
||||
}
|
||||
}
|
||||
|
||||
export const checkedObjectsAdd = (objectName) => {
|
||||
return {
|
||||
type: CHECKED_OBJECTS_ADD,
|
||||
objectName
|
||||
}
|
||||
}
|
||||
|
||||
export const checkedObjectsRemove = (objectName) => {
|
||||
return {
|
||||
type: CHECKED_OBJECTS_REMOVE,
|
||||
objectName
|
||||
}
|
||||
}
|
||||
|
||||
export const checkedObjectsReset = (objectName) => {
|
||||
return {
|
||||
type: CHECKED_OBJECTS_RESET,
|
||||
objectName
|
||||
}
|
||||
}
|
||||
@@ -1,800 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import classNames from 'classnames'
|
||||
import browserHistory from 'react-router/lib/browserHistory'
|
||||
import humanize from 'humanize'
|
||||
import Moment from 'moment'
|
||||
import Modal from 'react-bootstrap/lib/Modal'
|
||||
import ModalBody from 'react-bootstrap/lib/ModalBody'
|
||||
import ModalHeader from 'react-bootstrap/lib/ModalHeader'
|
||||
import Alert from 'react-bootstrap/lib/Alert'
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger'
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip'
|
||||
import Dropdown from 'react-bootstrap/lib/Dropdown'
|
||||
import MenuItem from 'react-bootstrap/lib/MenuItem'
|
||||
import InputGroup from '../components/InputGroup'
|
||||
import Dropzone from '../components/Dropzone'
|
||||
import ObjectsList from '../components/ObjectsList'
|
||||
import SideBar from '../components/SideBar'
|
||||
import Path from '../components/Path'
|
||||
import BrowserUpdate from '../components/BrowserUpdate'
|
||||
import UploadModal from '../components/UploadModal'
|
||||
import SettingsModal from '../components/SettingsModal'
|
||||
import PolicyInput from '../components/PolicyInput'
|
||||
import Policy from '../components/Policy'
|
||||
import BrowserDropdown from '../components/BrowserDropdown'
|
||||
import ConfirmModal from './ConfirmModal'
|
||||
import logo from '../../img/logo.svg'
|
||||
import * as actions from '../actions'
|
||||
import * as utils from '../utils'
|
||||
import * as mime from '../mime'
|
||||
import { minioBrowserPrefix } from '../constants'
|
||||
import CopyToClipboard from 'react-copy-to-clipboard'
|
||||
import storage from 'local-storage-fallback'
|
||||
import InfiniteScroll from 'react-infinite-scroller';
|
||||
|
||||
export default class Browse extends React.Component {
|
||||
componentDidMount() {
|
||||
const {web, dispatch, currentBucket} = this.props
|
||||
if (!web.LoggedIn()) return
|
||||
web.StorageInfo()
|
||||
.then(res => {
|
||||
let storageInfo = Object.assign({}, {
|
||||
total: res.storageInfo.Total,
|
||||
free: res.storageInfo.Free
|
||||
})
|
||||
storageInfo.used = storageInfo.total - storageInfo.free
|
||||
dispatch(actions.setStorageInfo(storageInfo))
|
||||
return web.ServerInfo()
|
||||
})
|
||||
.then(res => {
|
||||
let serverInfo = Object.assign({}, {
|
||||
version: res.MinioVersion,
|
||||
memory: res.MinioMemory,
|
||||
platform: res.MinioPlatform,
|
||||
runtime: res.MinioRuntime,
|
||||
info: res.MinioGlobalInfo
|
||||
})
|
||||
dispatch(actions.setServerInfo(serverInfo))
|
||||
})
|
||||
.catch(err => {
|
||||
dispatch(actions.showAlert({
|
||||
type: 'danger',
|
||||
message: err.message
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const {dispatch} = this.props
|
||||
// Clear out any stale message in the alert of Login page
|
||||
dispatch(actions.showAlert({
|
||||
type: 'danger',
|
||||
message: ''
|
||||
}))
|
||||
if (web.LoggedIn()) {
|
||||
web.ListBuckets()
|
||||
.then(res => {
|
||||
let buckets
|
||||
if (!res.buckets)
|
||||
buckets = []
|
||||
else
|
||||
buckets = res.buckets.map(bucket => bucket.name)
|
||||
if (buckets.length) {
|
||||
dispatch(actions.setBuckets(buckets))
|
||||
dispatch(actions.setVisibleBuckets(buckets))
|
||||
if (location.pathname === minioBrowserPrefix || location.pathname === minioBrowserPrefix + '/') {
|
||||
browserHistory.push(utils.pathJoin(buckets[0]))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
this.history = browserHistory.listen(({pathname}) => {
|
||||
let decPathname = decodeURI(pathname)
|
||||
if (decPathname === `${minioBrowserPrefix}/login`) return // FIXME: better organize routes and remove this
|
||||
if (!decPathname.endsWith('/'))
|
||||
decPathname += '/'
|
||||
if (decPathname === minioBrowserPrefix + '/') {
|
||||
return
|
||||
}
|
||||
let obj = utils.pathSlice(decPathname)
|
||||
if (!web.LoggedIn()) {
|
||||
dispatch(actions.setBuckets([obj.bucket]))
|
||||
dispatch(actions.setVisibleBuckets([obj.bucket]))
|
||||
}
|
||||
dispatch(actions.selectBucket(obj.bucket, obj.prefix))
|
||||
})
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.history()
|
||||
}
|
||||
|
||||
selectBucket(e, bucket) {
|
||||
e.preventDefault()
|
||||
if (bucket === this.props.currentBucket) return
|
||||
browserHistory.push(utils.pathJoin(bucket))
|
||||
}
|
||||
|
||||
searchBuckets(e) {
|
||||
e.preventDefault()
|
||||
let {buckets} = this.props
|
||||
this.props.dispatch(actions.setVisibleBuckets(buckets.filter(bucket => bucket.indexOf(e.target.value) > -1)))
|
||||
}
|
||||
|
||||
listObjects() {
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.listObjects())
|
||||
}
|
||||
|
||||
selectPrefix(e, prefix) {
|
||||
e.preventDefault()
|
||||
const {dispatch, currentPath, web, currentBucket} = this.props
|
||||
const encPrefix = encodeURI(prefix)
|
||||
if (prefix.endsWith('/') || prefix === '') {
|
||||
if (prefix === currentPath) return
|
||||
browserHistory.push(utils.pathJoin(currentBucket, encPrefix))
|
||||
} else {
|
||||
window.location = `${window.location.origin}/minio/download/${currentBucket}/${encPrefix}?token=${storage.getItem('token')}`
|
||||
}
|
||||
}
|
||||
|
||||
makeBucket(e) {
|
||||
e.preventDefault()
|
||||
const bucketName = this.refs.makeBucketRef.value
|
||||
this.refs.makeBucketRef.value = ''
|
||||
const {web, dispatch} = this.props
|
||||
this.hideMakeBucketModal()
|
||||
web.MakeBucket({
|
||||
bucketName
|
||||
})
|
||||
.then(() => {
|
||||
dispatch(actions.addBucket(bucketName))
|
||||
dispatch(actions.selectBucket(bucketName))
|
||||
})
|
||||
.catch(err => dispatch(actions.showAlert({
|
||||
type: 'danger',
|
||||
message: err.message
|
||||
})))
|
||||
}
|
||||
|
||||
hideMakeBucketModal() {
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.hideMakeBucketModal())
|
||||
}
|
||||
|
||||
showMakeBucketModal(e) {
|
||||
e.preventDefault()
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.showMakeBucketModal())
|
||||
}
|
||||
|
||||
showAbout(e) {
|
||||
e.preventDefault()
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.showAbout())
|
||||
}
|
||||
|
||||
hideAbout(e) {
|
||||
e.preventDefault()
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.hideAbout())
|
||||
}
|
||||
|
||||
showBucketPolicy(e) {
|
||||
e.preventDefault()
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.showBucketPolicy())
|
||||
}
|
||||
|
||||
hideBucketPolicy(e) {
|
||||
e.preventDefault()
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.hideBucketPolicy())
|
||||
}
|
||||
|
||||
uploadFile(e) {
|
||||
e.preventDefault()
|
||||
const {dispatch, buckets} = this.props
|
||||
|
||||
if (buckets.length === 0) {
|
||||
dispatch(actions.showAlert({
|
||||
type: 'danger',
|
||||
message: "Bucket needs to be created before trying to upload files."
|
||||
}))
|
||||
return
|
||||
}
|
||||
let file = e.target.files[0]
|
||||
e.target.value = null
|
||||
this.xhr = new XMLHttpRequest()
|
||||
dispatch(actions.uploadFile(file, this.xhr))
|
||||
}
|
||||
|
||||
removeObject() {
|
||||
const {web, dispatch, currentPath, currentBucket, deleteConfirmation, checkedObjects} = this.props
|
||||
let objects = []
|
||||
if (checkedObjects.length > 0) {
|
||||
objects = checkedObjects.map(obj => `${currentPath}${obj}`)
|
||||
} else {
|
||||
objects = [deleteConfirmation.object]
|
||||
}
|
||||
|
||||
web.RemoveObject({
|
||||
bucketname: currentBucket,
|
||||
objects: objects
|
||||
})
|
||||
.then(() => {
|
||||
this.hideDeleteConfirmation()
|
||||
if (checkedObjects.length > 0) {
|
||||
for (let i = 0; i < checkedObjects.length; i++) {
|
||||
dispatch(actions.removeObject(checkedObjects[i].replace(currentPath, '')))
|
||||
}
|
||||
dispatch(actions.checkedObjectsReset())
|
||||
} else {
|
||||
let delObject = deleteConfirmation.object.replace(currentPath, '')
|
||||
dispatch(actions.removeObject(delObject))
|
||||
}
|
||||
})
|
||||
.catch(e => dispatch(actions.showAlert({
|
||||
type: 'danger',
|
||||
message: e.message
|
||||
})))
|
||||
}
|
||||
|
||||
hideAlert(e) {
|
||||
e.preventDefault()
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.hideAlert())
|
||||
}
|
||||
|
||||
showDeleteConfirmation(e, object) {
|
||||
e.preventDefault()
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.showDeleteConfirmation(object))
|
||||
}
|
||||
|
||||
hideDeleteConfirmation() {
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.hideDeleteConfirmation())
|
||||
}
|
||||
|
||||
shareObject(e, object) {
|
||||
e.preventDefault()
|
||||
const {dispatch} = this.props
|
||||
// let expiry = 5 * 24 * 60 * 60 // 5 days expiry by default
|
||||
dispatch(actions.shareObject(object, 5, 0, 0))
|
||||
}
|
||||
|
||||
hideShareObjectModal() {
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.hideShareObject())
|
||||
}
|
||||
|
||||
dataType(name, contentType) {
|
||||
return mime.getDataType(name, contentType)
|
||||
}
|
||||
|
||||
sortObjectsByName(e) {
|
||||
const {dispatch, objects, sortNameOrder} = this.props
|
||||
dispatch(actions.setObjects(utils.sortObjectsByName(objects, !sortNameOrder)))
|
||||
dispatch(actions.setSortNameOrder(!sortNameOrder))
|
||||
}
|
||||
|
||||
sortObjectsBySize() {
|
||||
const {dispatch, objects, sortSizeOrder} = this.props
|
||||
dispatch(actions.setObjects(utils.sortObjectsBySize(objects, !sortSizeOrder)))
|
||||
dispatch(actions.setSortSizeOrder(!sortSizeOrder))
|
||||
}
|
||||
|
||||
sortObjectsByDate() {
|
||||
const {dispatch, objects, sortDateOrder} = this.props
|
||||
dispatch(actions.setObjects(utils.sortObjectsByDate(objects, !sortDateOrder)))
|
||||
dispatch(actions.setSortDateOrder(!sortDateOrder))
|
||||
}
|
||||
|
||||
logout(e) {
|
||||
const {web} = this.props
|
||||
e.preventDefault()
|
||||
web.Logout()
|
||||
browserHistory.push(`${minioBrowserPrefix}/login`)
|
||||
}
|
||||
|
||||
fullScreen(e) {
|
||||
e.preventDefault()
|
||||
let el = document.documentElement
|
||||
if (el.requestFullscreen) {
|
||||
el.requestFullscreen()
|
||||
}
|
||||
if (el.mozRequestFullScreen) {
|
||||
el.mozRequestFullScreen()
|
||||
}
|
||||
if (el.webkitRequestFullscreen) {
|
||||
el.webkitRequestFullscreen()
|
||||
}
|
||||
if (el.msRequestFullscreen) {
|
||||
el.msRequestFullscreen()
|
||||
}
|
||||
}
|
||||
|
||||
toggleSidebar(status) {
|
||||
this.props.dispatch(actions.setSidebarStatus(status))
|
||||
}
|
||||
|
||||
hideSidebar(event) {
|
||||
let e = event || window.event;
|
||||
|
||||
// Support all browsers.
|
||||
let target = e.srcElement || e.target;
|
||||
if (target.nodeType === 3) // Safari support.
|
||||
target = target.parentNode;
|
||||
|
||||
let targetID = target.id;
|
||||
if (!(targetID === 'feh-trigger')) {
|
||||
this.props.dispatch(actions.setSidebarStatus(false))
|
||||
}
|
||||
}
|
||||
|
||||
showSettings(e) {
|
||||
e.preventDefault()
|
||||
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.showSettings())
|
||||
}
|
||||
|
||||
showMessage() {
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.showAlert({
|
||||
type: 'success',
|
||||
message: 'Link copied to clipboard!'
|
||||
}))
|
||||
this.hideShareObjectModal()
|
||||
}
|
||||
|
||||
selectTexts() {
|
||||
this.refs.copyTextInput.select()
|
||||
}
|
||||
|
||||
handleExpireValue(targetInput, inc, object) {
|
||||
inc === -1 ? this.refs[targetInput].stepDown(1) : this.refs[targetInput].stepUp(1)
|
||||
|
||||
if (this.refs.expireDays.value == 7) {
|
||||
this.refs.expireHours.value = 0
|
||||
this.refs.expireMins.value = 0
|
||||
}
|
||||
if (this.refs.expireDays.value + this.refs.expireHours.value + this.refs.expireMins.value == 0) {
|
||||
this.refs.expireDays.value = 7
|
||||
}
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.shareObject(object, this.refs.expireDays.value, this.refs.expireHours.value, this.refs.expireMins.value))
|
||||
}
|
||||
|
||||
checkObject(e, objectName) {
|
||||
const {dispatch} = this.props
|
||||
e.target.checked ? dispatch(actions.checkedObjectsAdd(objectName)) : dispatch(actions.checkedObjectsRemove(objectName))
|
||||
}
|
||||
|
||||
downloadSelected() {
|
||||
const {dispatch} = this.props
|
||||
let req = {
|
||||
bucketName: this.props.currentBucket,
|
||||
objects: this.props.checkedObjects,
|
||||
prefix: this.props.currentPath
|
||||
}
|
||||
let requestUrl = location.origin + "/minio/zip?token=" + localStorage.token
|
||||
|
||||
this.xhr = new XMLHttpRequest()
|
||||
dispatch(actions.downloadSelected(requestUrl, req, this.xhr))
|
||||
}
|
||||
|
||||
clearSelected() {
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.checkedObjectsReset())
|
||||
}
|
||||
|
||||
render() {
|
||||
const {total, free} = this.props.storageInfo
|
||||
const {showMakeBucketModal, alert, sortNameOrder, sortSizeOrder, sortDateOrder, showAbout, showBucketPolicy, checkedObjects} = this.props
|
||||
const {version, memory, platform, runtime} = this.props.serverInfo
|
||||
const {sidebarStatus} = this.props
|
||||
const {showSettings} = this.props
|
||||
const {policies, currentBucket, currentPath} = this.props
|
||||
const {deleteConfirmation} = this.props
|
||||
const {shareObject} = this.props
|
||||
const {web, prefixWritable, istruncated} = this.props
|
||||
|
||||
// Don't always show the SettingsModal. This is done here instead of in
|
||||
// SettingsModal.js so as to allow for #componentWillMount to handle
|
||||
// the loading of the settings.
|
||||
let settingsModal = showSettings ? <SettingsModal /> : <noscript></noscript>
|
||||
|
||||
let alertBox = <Alert className={ classNames({
|
||||
'alert': true,
|
||||
'animated': true,
|
||||
'fadeInDown': alert.show,
|
||||
'fadeOutUp': !alert.show
|
||||
}) } bsStyle={ alert.type } onDismiss={ this.hideAlert.bind(this) }>
|
||||
<div className='text-center'>
|
||||
{ alert.message }
|
||||
</div>
|
||||
</Alert>
|
||||
// Make sure you don't show a fading out alert box on the initial web-page load.
|
||||
if (!alert.message)
|
||||
alertBox = ''
|
||||
|
||||
let signoutTooltip = <Tooltip id="tt-sign-out">
|
||||
Sign out
|
||||
</Tooltip>
|
||||
let uploadTooltip = <Tooltip id="tt-upload-file">
|
||||
Upload file
|
||||
</Tooltip>
|
||||
let makeBucketTooltip = <Tooltip id="tt-create-bucket">
|
||||
Create bucket
|
||||
</Tooltip>
|
||||
let loginButton = ''
|
||||
let browserDropdownButton = ''
|
||||
let storageUsageDetails = ''
|
||||
|
||||
let used = total - free
|
||||
let usedPercent = (used / total) * 100 + '%'
|
||||
let freePercent = free * 100 / total
|
||||
|
||||
if (web.LoggedIn()) {
|
||||
browserDropdownButton = <BrowserDropdown fullScreenFunc={ this.fullScreen.bind(this) }
|
||||
aboutFunc={ this.showAbout.bind(this) }
|
||||
settingsFunc={ this.showSettings.bind(this) }
|
||||
logoutFunc={ this.logout.bind(this) } />
|
||||
} else {
|
||||
loginButton = <a className='btn btn-danger' href='/minio/login'>Login</a>
|
||||
}
|
||||
|
||||
if (web.LoggedIn()) {
|
||||
if (!(used === 0 && free === 0)) {
|
||||
storageUsageDetails = <div className="feh-usage">
|
||||
<div className="fehu-chart">
|
||||
<div style={ { width: usedPercent } }></div>
|
||||
</div>
|
||||
<ul>
|
||||
<li>
|
||||
<span>Used: </span>
|
||||
{ humanize.filesize(total - free) }
|
||||
</li>
|
||||
<li className="pull-right">
|
||||
<span>Free: </span>
|
||||
{ humanize.filesize(total - used) }
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
let createButton = ''
|
||||
if (web.LoggedIn()) {
|
||||
createButton = <Dropdown dropup className="feb-actions" id="fe-action-toggle">
|
||||
<Dropdown.Toggle noCaret className="feba-toggle">
|
||||
<span><i className="fa fa-plus"></i></span>
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
<OverlayTrigger placement="left" overlay={ uploadTooltip }>
|
||||
<a href="#" className="feba-btn feba-upload">
|
||||
<input type="file"
|
||||
onChange={ this.uploadFile.bind(this) }
|
||||
style={ { display: 'none' } }
|
||||
id="file-input"></input>
|
||||
<label htmlFor="file-input"> <i className="fa fa-cloud-upload"></i> </label>
|
||||
</a>
|
||||
</OverlayTrigger>
|
||||
<OverlayTrigger placement="left" overlay={ makeBucketTooltip }>
|
||||
<a href="#" className="feba-btn feba-bucket" onClick={ this.showMakeBucketModal.bind(this) }><i className="fa fa-hdd-o"></i></a>
|
||||
</OverlayTrigger>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
|
||||
} else {
|
||||
if (prefixWritable)
|
||||
createButton = <Dropdown dropup className="feb-actions" id="fe-action-toggle">
|
||||
<Dropdown.Toggle noCaret className="feba-toggle">
|
||||
<span><i className="fa fa-plus"></i></span>
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
<OverlayTrigger placement="left" overlay={ uploadTooltip }>
|
||||
<a href="#" className="feba-btn feba-upload">
|
||||
<input type="file"
|
||||
onChange={ this.uploadFile.bind(this) }
|
||||
style={ { display: 'none' } }
|
||||
id="file-input"></input>
|
||||
<label htmlFor="file-input"> <i className="fa fa-cloud-upload"></i> </label>
|
||||
</a>
|
||||
</OverlayTrigger>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ classNames({
|
||||
'file-explorer': true,
|
||||
'toggled': sidebarStatus
|
||||
}) }>
|
||||
<SideBar searchBuckets={ this.searchBuckets.bind(this) }
|
||||
selectBucket={ this.selectBucket.bind(this) }
|
||||
clickOutside={ this.hideSidebar.bind(this) }
|
||||
showPolicy={ this.showBucketPolicy.bind(this) } />
|
||||
<div className="fe-body">
|
||||
<div className={ 'list-actions' + (classNames({
|
||||
' list-actions-toggled': checkedObjects.length > 0
|
||||
})) }>
|
||||
<span className="la-label"><i className="fa fa-check-circle" /> { checkedObjects.length } Objects selected</span>
|
||||
<span className="la-actions pull-right"><button onClick={ this.downloadSelected.bind(this) }> Download all as zip </button></span>
|
||||
<span className="la-actions pull-right"><button onClick={ this.showDeleteConfirmation.bind(this) }> Delete selected </button></span>
|
||||
<i className="la-close fa fa-times" onClick={ this.clearSelected.bind(this) }></i>
|
||||
</div>
|
||||
<Dropzone>
|
||||
{ alertBox }
|
||||
<header className="fe-header-mobile hidden-lg hidden-md">
|
||||
<div id="feh-trigger" className={ 'feh-trigger ' + (classNames({
|
||||
'feht-toggled': sidebarStatus
|
||||
})) } onClick={ this.toggleSidebar.bind(this, !sidebarStatus) }>
|
||||
<div className="feht-lines">
|
||||
<div className="top"></div>
|
||||
<div className="center"></div>
|
||||
<div className="bottom"></div>
|
||||
</div>
|
||||
</div>
|
||||
<img className="mh-logo" src={ logo } alt="" />
|
||||
</header>
|
||||
<header className="fe-header">
|
||||
<Path selectPrefix={ this.selectPrefix.bind(this) } />
|
||||
{ storageUsageDetails }
|
||||
<ul className="feh-actions">
|
||||
<BrowserUpdate />
|
||||
{ loginButton }
|
||||
{ browserDropdownButton }
|
||||
</ul>
|
||||
</header>
|
||||
<div className="feb-container">
|
||||
<header className="fesl-row" data-type="folder">
|
||||
<div className="fesl-item fesl-item-icon"></div>
|
||||
<div className="fesl-item fesl-item-name" onClick={ this.sortObjectsByName.bind(this) } data-sort="name">
|
||||
Name
|
||||
<i className={ classNames({
|
||||
'fesli-sort': true,
|
||||
'fa': true,
|
||||
'fa-sort-alpha-desc': sortNameOrder,
|
||||
'fa-sort-alpha-asc': !sortNameOrder
|
||||
}) } />
|
||||
</div>
|
||||
<div className="fesl-item fesl-item-size" onClick={ this.sortObjectsBySize.bind(this) } data-sort="size">
|
||||
Size
|
||||
<i className={ classNames({
|
||||
'fesli-sort': true,
|
||||
'fa': true,
|
||||
'fa-sort-amount-desc': sortSizeOrder,
|
||||
'fa-sort-amount-asc': !sortSizeOrder
|
||||
}) } />
|
||||
</div>
|
||||
<div className="fesl-item fesl-item-modified" onClick={ this.sortObjectsByDate.bind(this) } data-sort="last-modified">
|
||||
Last Modified
|
||||
<i className={ classNames({
|
||||
'fesli-sort': true,
|
||||
'fa': true,
|
||||
'fa-sort-numeric-desc': sortDateOrder,
|
||||
'fa-sort-numeric-asc': !sortDateOrder
|
||||
}) } />
|
||||
</div>
|
||||
<div className="fesl-item fesl-item-actions"></div>
|
||||
</header>
|
||||
</div>
|
||||
<div className="feb-container">
|
||||
<InfiniteScroll loadMore={ this.listObjects.bind(this) }
|
||||
hasMore={ istruncated }
|
||||
useWindow={ true }
|
||||
initialLoad={ false }>
|
||||
<ObjectsList dataType={ this.dataType.bind(this) }
|
||||
selectPrefix={ this.selectPrefix.bind(this) }
|
||||
showDeleteConfirmation={ this.showDeleteConfirmation.bind(this) }
|
||||
shareObject={ this.shareObject.bind(this) }
|
||||
checkObject={ this.checkObject.bind(this) }
|
||||
checkedObjectsArray={ checkedObjects } />
|
||||
</InfiniteScroll>
|
||||
<div className="text-center" style={ { display: (istruncated && currentBucket) ? 'block' : 'none' } }>
|
||||
<span>Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
<UploadModal />
|
||||
{ createButton }
|
||||
<Modal className="modal-create-bucket"
|
||||
bsSize="small"
|
||||
animation={ false }
|
||||
show={ showMakeBucketModal }
|
||||
onHide={ this.hideMakeBucketModal.bind(this) }>
|
||||
<button className="close close-alt" onClick={ this.hideMakeBucketModal.bind(this) }>
|
||||
<span>×</span>
|
||||
</button>
|
||||
<ModalBody>
|
||||
<form onSubmit={ this.makeBucket.bind(this) }>
|
||||
<div className="input-group">
|
||||
<input className="ig-text"
|
||||
type="text"
|
||||
ref="makeBucketRef"
|
||||
placeholder="Bucket Name"
|
||||
autoFocus/>
|
||||
<i className="ig-helpers"></i>
|
||||
</div>
|
||||
</form>
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
<Modal className="modal-about modal-dark"
|
||||
animation={ false }
|
||||
show={ showAbout }
|
||||
onHide={ this.hideAbout.bind(this) }>
|
||||
<button className="close" onClick={ this.hideAbout.bind(this) }>
|
||||
<span>×</span>
|
||||
</button>
|
||||
<div className="ma-inner">
|
||||
<div className="mai-item hidden-xs">
|
||||
<a href="https://minio.io" target="_blank"><img className="maii-logo" src={ logo } alt="" /></a>
|
||||
</div>
|
||||
<div className="mai-item">
|
||||
<ul className="maii-list">
|
||||
<li>
|
||||
<div>
|
||||
Version
|
||||
</div>
|
||||
<small>{ version }</small>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Memory
|
||||
</div>
|
||||
<small>{ memory }</small>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Platform
|
||||
</div>
|
||||
<small>{ platform }</small>
|
||||
</li>
|
||||
<li>
|
||||
<div>
|
||||
Runtime
|
||||
</div>
|
||||
<small>{ runtime }</small>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<Modal className="modal-policy"
|
||||
animation={ false }
|
||||
show={ showBucketPolicy }
|
||||
onHide={ this.hideBucketPolicy.bind(this) }>
|
||||
<ModalHeader>
|
||||
Bucket Policy (
|
||||
{ currentBucket })
|
||||
<button className="close close-alt" onClick={ this.hideBucketPolicy.bind(this) }>
|
||||
<span>×</span>
|
||||
</button>
|
||||
</ModalHeader>
|
||||
<div className="pm-body">
|
||||
<PolicyInput bucket={ currentBucket } />
|
||||
{ policies.map((policy, i) => <Policy key={ i } prefix={ policy.prefix } policy={ policy.policy } />
|
||||
) }
|
||||
</div>
|
||||
</Modal>
|
||||
<ConfirmModal show={ deleteConfirmation.show }
|
||||
icon='fa fa-exclamation-triangle mci-red'
|
||||
text='Are you sure you want to delete?'
|
||||
sub='This cannot be undone!'
|
||||
okText='Delete'
|
||||
cancelText='Cancel'
|
||||
okHandler={ this.removeObject.bind(this) }
|
||||
cancelHandler={ this.hideDeleteConfirmation.bind(this) }>
|
||||
</ConfirmModal>
|
||||
<Modal show={ shareObject.show }
|
||||
animation={ false }
|
||||
onHide={ this.hideShareObjectModal.bind(this) }
|
||||
bsSize="small">
|
||||
<ModalHeader>
|
||||
Share Object
|
||||
</ModalHeader>
|
||||
<ModalBody>
|
||||
<div className="input-group copy-text">
|
||||
<label>
|
||||
Shareable Link
|
||||
</label>
|
||||
<input type="text"
|
||||
ref="copyTextInput"
|
||||
readOnly="readOnly"
|
||||
value={ window.location.protocol + '//' + shareObject.url }
|
||||
onClick={ this.selectTexts.bind(this) } />
|
||||
</div>
|
||||
<div className="input-group" style={ { display: web.LoggedIn() ? 'block' : 'none' } }>
|
||||
<label>
|
||||
Expires in (Max 7 days)
|
||||
</label>
|
||||
<div className="set-expire">
|
||||
<div className="set-expire-item">
|
||||
<i className="set-expire-increase" onClick={ this.handleExpireValue.bind(this, 'expireDays', 1, shareObject.object) } />
|
||||
<div className="set-expire-title">
|
||||
Days
|
||||
</div>
|
||||
<div className="set-expire-value">
|
||||
<input ref="expireDays"
|
||||
type="number"
|
||||
min={ 0 }
|
||||
max={ 7 }
|
||||
defaultValue={ 5 }
|
||||
readOnly="readOnly"
|
||||
/>
|
||||
</div>
|
||||
<i className="set-expire-decrease" onClick={ this.handleExpireValue.bind(this, 'expireDays', -1, shareObject.object) } />
|
||||
</div>
|
||||
<div className="set-expire-item">
|
||||
<i className="set-expire-increase" onClick={ this.handleExpireValue.bind(this, 'expireHours', 1, shareObject.object) } />
|
||||
<div className="set-expire-title">
|
||||
Hours
|
||||
</div>
|
||||
<div className="set-expire-value">
|
||||
<input ref="expireHours"
|
||||
type="number"
|
||||
min={ 0 }
|
||||
max={ 23 }
|
||||
defaultValue={ 0 }
|
||||
readOnly="readOnly"
|
||||
/>
|
||||
</div>
|
||||
<i className="set-expire-decrease" onClick={ this.handleExpireValue.bind(this, 'expireHours', -1, shareObject.object) } />
|
||||
</div>
|
||||
<div className="set-expire-item">
|
||||
<i className="set-expire-increase" onClick={ this.handleExpireValue.bind(this, 'expireMins', 1, shareObject.object) } />
|
||||
<div className="set-expire-title">
|
||||
Minutes
|
||||
</div>
|
||||
<div className="set-expire-value">
|
||||
<input ref="expireMins"
|
||||
type="number"
|
||||
min={ 0 }
|
||||
max={ 59 }
|
||||
defaultValue={ 0 }
|
||||
readOnly="readOnly"
|
||||
/>
|
||||
</div>
|
||||
<i className="set-expire-decrease" onClick={ this.handleExpireValue.bind(this, 'expireMins', -1, shareObject.object) } />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ModalBody>
|
||||
<div className="modal-footer">
|
||||
<CopyToClipboard text={ window.location.protocol + '//' + shareObject.url } onCopy={ this.showMessage.bind(this) }>
|
||||
<button className="btn btn-success">
|
||||
Copy Link
|
||||
</button>
|
||||
</CopyToClipboard>
|
||||
<button className="btn btn-link" onClick={ this.hideShareObjectModal.bind(this) }>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</Modal>
|
||||
{ settingsModal }
|
||||
</Dropzone>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016, 2017 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import connect from 'react-redux/lib/components/connect'
|
||||
import Dropdown from 'react-bootstrap/lib/Dropdown'
|
||||
|
||||
let BrowserDropdown = ({fullScreenFunc, aboutFunc, settingsFunc, logoutFunc}) => {
|
||||
return (
|
||||
<li>
|
||||
<Dropdown pullRight id="top-right-menu">
|
||||
<Dropdown.Toggle noCaret>
|
||||
<i className="fa fa-reorder"></i>
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu className="dropdown-menu-right">
|
||||
<li>
|
||||
<a target="_blank" href="https://github.com/minio/minio">Github <i className="fa fa-github"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" onClick={ fullScreenFunc }>Fullscreen <i className="fa fa-expand"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://docs.minio.io/">Documentation <i className="fa fa-book"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a target="_blank" href="https://slack.minio.io">Ask for help <i className="fa fa-question-circle"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" onClick={ aboutFunc }>About <i className="fa fa-info-circle"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" onClick={ settingsFunc }>Settings <i className="fa fa-cog"></i></a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="" onClick={ logoutFunc }>Sign Out <i className="fa fa-sign-out"></i></a>
|
||||
</li>
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
export default connect(state => state)(BrowserDropdown)
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import connect from 'react-redux/lib/components/connect'
|
||||
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip'
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger'
|
||||
|
||||
let BrowserUpdate = ({latestUiVersion}) => {
|
||||
// Don't show an update if we're already updated!
|
||||
if (latestUiVersion === currentUiVersion) return ( <noscript></noscript> )
|
||||
|
||||
return (
|
||||
<li className="hidden-xs hidden-sm">
|
||||
<a href="">
|
||||
<OverlayTrigger placement="left" overlay={ <Tooltip id="tt-version-update">
|
||||
New update available. Click to refresh.
|
||||
</Tooltip> }> <i className="fa fa-refresh"></i> </OverlayTrigger>
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
export default connect(state => {
|
||||
return {
|
||||
latestUiVersion: state.latestUiVersion
|
||||
}
|
||||
})(BrowserUpdate)
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import Modal from 'react-bootstrap/lib/Modal'
|
||||
import ModalBody from 'react-bootstrap/lib/ModalBody'
|
||||
|
||||
let ConfirmModal = ({baseClass, icon, text, sub, okText, cancelText, okHandler, cancelHandler, show}) => {
|
||||
return (
|
||||
<Modal bsSize="small"
|
||||
animation={ false }
|
||||
show={ show }
|
||||
className={ "modal-confirm " + (baseClass || '') }>
|
||||
<ModalBody>
|
||||
<div className="mc-icon">
|
||||
<i className={ icon }></i>
|
||||
</div>
|
||||
<div className="mc-text">
|
||||
{ text }
|
||||
</div>
|
||||
<div className="mc-sub">
|
||||
{ sub }
|
||||
</div>
|
||||
</ModalBody>
|
||||
<div className="modal-footer">
|
||||
<button className="btn btn-danger" onClick={ okHandler }>
|
||||
{ okText }
|
||||
</button>
|
||||
<button className="btn btn-link" onClick={ cancelHandler }>
|
||||
{ cancelText }
|
||||
</button>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
export default ConfirmModal
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import ReactDropzone from 'react-dropzone'
|
||||
import * as actions from '../actions'
|
||||
|
||||
// Dropzone is a drag-and-drop element for uploading files. It will create a
|
||||
// landing zone of sorts that automatically receives the files.
|
||||
export default class Dropzone extends React.Component {
|
||||
|
||||
onDrop(files) {
|
||||
// FIXME: Currently you can upload multiple files, but only one abort
|
||||
// modal will be shown, and progress updates will only occur for one
|
||||
// file at a time. See #171.
|
||||
files.forEach(file => {
|
||||
let req = new XMLHttpRequest()
|
||||
|
||||
// Dispatch the upload.
|
||||
web.dispatch(actions.uploadFile(file, req))
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
// Overwrite the default styling from react-dropzone; otherwise it
|
||||
// won't handle child elements correctly.
|
||||
const style = {
|
||||
height: '100%',
|
||||
borderWidth: '0',
|
||||
borderStyle: 'dashed',
|
||||
borderColor: '#fff'
|
||||
}
|
||||
const activeStyle = {
|
||||
borderWidth: '2px',
|
||||
borderColor: '#777'
|
||||
}
|
||||
const rejectStyle = {
|
||||
backgroundColor: '#ffdddd'
|
||||
}
|
||||
|
||||
// disableClick means that it won't trigger a file upload box when
|
||||
// the user clicks on a file.
|
||||
return (
|
||||
<ReactDropzone style={ style }
|
||||
activeStyle={ activeStyle }
|
||||
rejectStyle={ rejectStyle }
|
||||
disableClick={ true }
|
||||
onDrop={ this.onDrop }>
|
||||
{ this.props.children }
|
||||
</ReactDropzone>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
|
||||
let InputGroup = ({label, id, name, value, onChange, type, spellCheck, required, readonly, autoComplete, align, className}) => {
|
||||
var input = <input id={ id }
|
||||
name={ name }
|
||||
value={ value }
|
||||
onChange={ onChange }
|
||||
className="ig-text"
|
||||
type={ type }
|
||||
spellCheck={ spellCheck }
|
||||
required={ required }
|
||||
autoComplete={ autoComplete } />
|
||||
if (readonly)
|
||||
input = <input id={ id }
|
||||
name={ name }
|
||||
value={ value }
|
||||
onChange={ onChange }
|
||||
className="ig-text"
|
||||
type={ type }
|
||||
spellCheck={ spellCheck }
|
||||
required={ required }
|
||||
autoComplete={ autoComplete }
|
||||
disabled />
|
||||
return <div className={ "input-group " + align + ' ' + className }>
|
||||
{ input }
|
||||
<i className="ig-helpers"></i>
|
||||
<label className="ig-label">
|
||||
{ label }
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
|
||||
export default InputGroup
|
||||
@@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import classNames from 'classnames'
|
||||
import logo from '../../img/logo.svg'
|
||||
import Alert from 'react-bootstrap/lib/Alert'
|
||||
import * as actions from '../actions'
|
||||
import InputGroup from '../components/InputGroup'
|
||||
|
||||
export default class Login extends React.Component {
|
||||
handleSubmit(event) {
|
||||
event.preventDefault()
|
||||
const {web, dispatch, loginRedirectPath} = this.props
|
||||
let message = ''
|
||||
if (!document.getElementById('accessKey').value) {
|
||||
message = 'Secret Key cannot be empty'
|
||||
}
|
||||
if (!document.getElementById('secretKey').value) {
|
||||
message = 'Access Key cannot be empty'
|
||||
}
|
||||
if (message) {
|
||||
dispatch(actions.showAlert({
|
||||
type: 'danger',
|
||||
message
|
||||
}))
|
||||
return
|
||||
}
|
||||
web.Login({
|
||||
username: document.getElementById('accessKey').value,
|
||||
password: document.getElementById('secretKey').value
|
||||
})
|
||||
.then((res) => {
|
||||
this.context.router.push(loginRedirectPath)
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(actions.setLoginError())
|
||||
dispatch(actions.showAlert({
|
||||
type: 'danger',
|
||||
message: e.message
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const {dispatch} = this.props
|
||||
// Clear out any stale message in the alert of previous page
|
||||
dispatch(actions.showAlert({
|
||||
type: 'danger',
|
||||
message: ''
|
||||
}))
|
||||
document.body.classList.add('is-guest')
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.body.classList.remove('is-guest')
|
||||
}
|
||||
|
||||
hideAlert() {
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.hideAlert())
|
||||
}
|
||||
|
||||
render() {
|
||||
const {alert} = this.props
|
||||
let alertBox = <Alert className={ 'alert animated ' + (alert.show ? 'fadeInDown' : 'fadeOutUp') } bsStyle={ alert.type } onDismiss={ this.hideAlert.bind(this) }>
|
||||
<div className='text-center'>
|
||||
{ alert.message }
|
||||
</div>
|
||||
</Alert>
|
||||
// Make sure you don't show a fading out alert box on the initial web-page load.
|
||||
if (!alert.message)
|
||||
alertBox = ''
|
||||
return (
|
||||
<div className="login">
|
||||
{ alertBox }
|
||||
<div className="l-wrap">
|
||||
<form onSubmit={ this.handleSubmit.bind(this) }>
|
||||
<InputGroup className="ig-dark"
|
||||
label="Access Key"
|
||||
id="accessKey"
|
||||
name="username"
|
||||
type="text"
|
||||
spellCheck="false"
|
||||
required="required"
|
||||
autoComplete="username">
|
||||
</InputGroup>
|
||||
<InputGroup className="ig-dark"
|
||||
label="Secret Key"
|
||||
id="secretKey"
|
||||
name="password"
|
||||
type="password"
|
||||
spellCheck="false"
|
||||
required="required"
|
||||
autoComplete="new-password">
|
||||
</InputGroup>
|
||||
<button className="lw-btn" type="submit">
|
||||
<i className="fa fa-sign-in"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div className="l-footer">
|
||||
<a className="lf-logo" href=""><img src={ logo } alt="" /></a>
|
||||
<div className="lf-server">
|
||||
{ window.location.host }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Login.contextTypes = {
|
||||
router: React.PropTypes.object.isRequired
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import Moment from 'moment'
|
||||
import humanize from 'humanize'
|
||||
import connect from 'react-redux/lib/components/connect'
|
||||
import Dropdown from 'react-bootstrap/lib/Dropdown'
|
||||
|
||||
let ObjectsList = ({objects, currentPath, selectPrefix, dataType, showDeleteConfirmation, shareObject, loadPath, checkObject, checkedObjectsArray}) => {
|
||||
const list = objects.map((object, i) => {
|
||||
let size = object.name.endsWith('/') ? '-' : humanize.filesize(object.size)
|
||||
let lastModified = object.name.endsWith('/') ? '-' : Moment(object.lastModified).format('lll')
|
||||
let loadingClass = loadPath === `${currentPath}${object.name}` ? 'fesl-loading' : ''
|
||||
let actionButtons = ''
|
||||
let deleteButton = ''
|
||||
if (web.LoggedIn())
|
||||
deleteButton = <a href="" className="fiad-action" onClick={ (e) => showDeleteConfirmation(e, `${currentPath}${object.name}`) }><i className="fa fa-trash"></i></a>
|
||||
|
||||
if (!checkedObjectsArray.length > 0) {
|
||||
if (!object.name.endsWith('/')) {
|
||||
actionButtons = <Dropdown id={ "fia-dropdown-" + object.name.replace('.', '-') }>
|
||||
<Dropdown.Toggle noCaret className="fia-toggle"></Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
<a href="" className="fiad-action" onClick={ (e) => shareObject(e, `${currentPath}${object.name}`) }><i className="fa fa-copy"></i></a>
|
||||
{ deleteButton }
|
||||
</Dropdown.Menu>
|
||||
</Dropdown>
|
||||
}
|
||||
}
|
||||
|
||||
let activeClass = ''
|
||||
let isChecked = ''
|
||||
|
||||
if (checkedObjectsArray.indexOf(object.name) > -1) {
|
||||
activeClass = ' fesl-row-selected'
|
||||
isChecked = true
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={ i } className={ "fesl-row " + loadingClass + activeClass } data-type={ dataType(object.name, object.contentType) }>
|
||||
<div className="fesl-item fesl-item-icon">
|
||||
<div className="fi-select">
|
||||
<input type="checkbox"
|
||||
name={ object.name }
|
||||
checked={ isChecked }
|
||||
onChange={ (e) => checkObject(e, object.name) } />
|
||||
<i className="fis-icon"></i>
|
||||
<i className="fis-helper"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div className="fesl-item fesl-item-name">
|
||||
<a href="" onClick={ (e) => selectPrefix(e, `${currentPath}${object.name}`) }>
|
||||
{ object.name }
|
||||
</a>
|
||||
</div>
|
||||
<div className="fesl-item fesl-item-size">
|
||||
{ size }
|
||||
</div>
|
||||
<div className="fesl-item fesl-item-modified">
|
||||
{ lastModified }
|
||||
</div>
|
||||
<div className="fesl-item fesl-item-actions">
|
||||
{ actionButtons }
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
return (
|
||||
<div>
|
||||
{ list }
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Subscribe it to state changes.
|
||||
export default connect(state => {
|
||||
return {
|
||||
objects: state.objects,
|
||||
currentPath: state.currentPath,
|
||||
loadPath: state.loadPath
|
||||
}
|
||||
})(ObjectsList)
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import connect from 'react-redux/lib/components/connect'
|
||||
|
||||
let Path = ({currentBucket, currentPath, selectPrefix}) => {
|
||||
let dirPath = []
|
||||
let path = ''
|
||||
if (currentPath) {
|
||||
path = currentPath.split('/').map((dir, i) => {
|
||||
dirPath.push(dir)
|
||||
let dirPath_ = dirPath.join('/') + '/'
|
||||
return <span key={ i }><a href="" onClick={ (e) => selectPrefix(e, dirPath_) }>{ dir }</a></span>
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<h2><span className="main"><a onClick={ (e) => selectPrefix(e, '') } href="">{ currentBucket }</a></span>{ path }</h2>
|
||||
)
|
||||
}
|
||||
|
||||
export default connect(state => {
|
||||
return {
|
||||
currentBucket: state.currentBucket,
|
||||
currentPath: state.currentPath
|
||||
}
|
||||
})(Path)
|
||||
@@ -1,80 +0,0 @@
|
||||
import { READ_ONLY, WRITE_ONLY, READ_WRITE } from '../constants'
|
||||
|
||||
import React, { Component, PropTypes } from 'react'
|
||||
import connect from 'react-redux/lib/components/connect'
|
||||
import classnames from 'classnames'
|
||||
import * as actions from '../actions'
|
||||
|
||||
class Policy extends Component {
|
||||
constructor(props, context) {
|
||||
super(props, context)
|
||||
this.state = {}
|
||||
}
|
||||
|
||||
handlePolicyChange(e) {
|
||||
this.setState({
|
||||
policy: {
|
||||
policy: e.target.value
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
removePolicy(e) {
|
||||
e.preventDefault()
|
||||
const {dispatch, currentBucket, prefix} = this.props
|
||||
let newPrefix = prefix.replace(currentBucket + '/', '')
|
||||
newPrefix = newPrefix.replace('*', '')
|
||||
web.SetBucketPolicy({
|
||||
bucketName: currentBucket,
|
||||
prefix: newPrefix,
|
||||
policy: 'none'
|
||||
})
|
||||
.then(() => {
|
||||
dispatch(actions.setPolicies(this.props.policies.filter(policy => policy.prefix != prefix)))
|
||||
})
|
||||
.catch(e => dispatch(actions.showAlert({
|
||||
type: 'danger',
|
||||
message: e.message,
|
||||
})))
|
||||
}
|
||||
|
||||
render() {
|
||||
const {policy, prefix, currentBucket} = this.props
|
||||
let newPrefix = prefix.replace(currentBucket + '/', '')
|
||||
newPrefix = newPrefix.replace('*', '')
|
||||
|
||||
if (!newPrefix)
|
||||
newPrefix = '*'
|
||||
|
||||
return (
|
||||
<div className="pmb-list">
|
||||
<div className="pmbl-item">
|
||||
{ newPrefix }
|
||||
</div>
|
||||
<div className="pmbl-item">
|
||||
<select className="form-control"
|
||||
disabled
|
||||
value={ policy }
|
||||
onChange={ this.handlePolicyChange.bind(this) }>
|
||||
<option value={ READ_ONLY }>
|
||||
Read Only
|
||||
</option>
|
||||
<option value={ WRITE_ONLY }>
|
||||
Write Only
|
||||
</option>
|
||||
<option value={ READ_WRITE }>
|
||||
Read and Write
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="pmbl-item">
|
||||
<button className="btn btn-block btn-danger" onClick={ this.removePolicy.bind(this) }>
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(state => state)(Policy)
|
||||
@@ -1,98 +0,0 @@
|
||||
import { READ_ONLY, WRITE_ONLY, READ_WRITE } from '../constants'
|
||||
import React, { Component, PropTypes } from 'react'
|
||||
import connect from 'react-redux/lib/components/connect'
|
||||
import classnames from 'classnames'
|
||||
import * as actions from '../actions'
|
||||
|
||||
class PolicyInput extends Component {
|
||||
componentDidMount() {
|
||||
const {web, dispatch} = this.props
|
||||
this.prefix.focus()
|
||||
web.ListAllBucketPolicies({
|
||||
bucketName: this.props.currentBucket
|
||||
}).then(res => {
|
||||
let policies = res.policies
|
||||
if (policies) dispatch(actions.setPolicies(policies))
|
||||
}).catch(err => {
|
||||
dispatch(actions.showAlert({
|
||||
type: 'danger',
|
||||
message: err.message
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.setPolicies([]))
|
||||
}
|
||||
|
||||
handlePolicySubmit(e) {
|
||||
e.preventDefault()
|
||||
const {web, dispatch, currentBucket} = this.props
|
||||
|
||||
let prefix = currentBucket + '/' + this.prefix.value
|
||||
let policy = this.policy.value
|
||||
|
||||
if (!prefix.endsWith('*')) prefix = prefix + '*'
|
||||
|
||||
let prefixAlreadyExists = this.props.policies.some(elem => prefix === elem.prefix)
|
||||
|
||||
if (prefixAlreadyExists) {
|
||||
dispatch(actions.showAlert({
|
||||
type: 'danger',
|
||||
message: "Policy for this prefix already exists."
|
||||
}))
|
||||
return
|
||||
}
|
||||
|
||||
web.SetBucketPolicy({
|
||||
bucketName: this.props.currentBucket,
|
||||
prefix: this.prefix.value,
|
||||
policy: this.policy.value
|
||||
})
|
||||
.then(() => {
|
||||
dispatch(actions.setPolicies([{
|
||||
policy, prefix
|
||||
}, ...this.props.policies]))
|
||||
this.prefix.value = ''
|
||||
})
|
||||
.catch(e => dispatch(actions.showAlert({
|
||||
type: 'danger',
|
||||
message: e.message,
|
||||
})))
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<header className="pmb-list">
|
||||
<div className="pmbl-item">
|
||||
<input type="text"
|
||||
ref={ prefix => this.prefix = prefix }
|
||||
className="form-control"
|
||||
placeholder="Prefix"
|
||||
editable={ true } />
|
||||
</div>
|
||||
<div className="pmbl-item">
|
||||
<select ref={ policy => this.policy = policy } className="form-control">
|
||||
<option value={ READ_ONLY }>
|
||||
Read Only
|
||||
</option>
|
||||
<option value={ WRITE_ONLY }>
|
||||
Write Only
|
||||
</option>
|
||||
<option value={ READ_WRITE }>
|
||||
Read and Write
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="pmbl-item">
|
||||
<button className="btn btn-block btn-primary" onClick={ this.handlePolicySubmit.bind(this) }>
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(state => state)(PolicyInput)
|
||||
@@ -1,204 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import connect from 'react-redux/lib/components/connect'
|
||||
import * as actions from '../actions'
|
||||
|
||||
import Tooltip from 'react-bootstrap/lib/Tooltip'
|
||||
import Modal from 'react-bootstrap/lib/Modal'
|
||||
import ModalBody from 'react-bootstrap/lib/ModalBody'
|
||||
import ModalHeader from 'react-bootstrap/lib/ModalHeader'
|
||||
import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger'
|
||||
import InputGroup from './InputGroup'
|
||||
|
||||
class SettingsModal extends React.Component {
|
||||
|
||||
// When the settings are shown, it loads the access key and secret key.
|
||||
componentWillMount() {
|
||||
const {web, dispatch} = this.props
|
||||
const {serverInfo} = this.props
|
||||
|
||||
let accessKeyEnv = ''
|
||||
let secretKeyEnv = ''
|
||||
// Check environment variables first.
|
||||
if (serverInfo.info.isEnvCreds) {
|
||||
dispatch(actions.setSettings({
|
||||
accessKey: 'xxxxxxxxx',
|
||||
secretKey: 'xxxxxxxxx',
|
||||
keysReadOnly: true
|
||||
}))
|
||||
} else {
|
||||
web.GetAuth()
|
||||
.then(data => {
|
||||
dispatch(actions.setSettings({
|
||||
accessKey: data.accessKey,
|
||||
secretKey: data.secretKey
|
||||
}))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// When they are re-hidden, the keys are unloaded from memory.
|
||||
componentWillUnmount() {
|
||||
const {dispatch} = this.props
|
||||
|
||||
dispatch(actions.setSettings({
|
||||
accessKey: '',
|
||||
secretKey: '',
|
||||
secretKeyVisible: false
|
||||
}))
|
||||
dispatch(actions.hideSettings())
|
||||
}
|
||||
|
||||
// Handle field changes from inside the modal.
|
||||
accessKeyChange(e) {
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.setSettings({
|
||||
accessKey: e.target.value
|
||||
}))
|
||||
}
|
||||
|
||||
secretKeyChange(e) {
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.setSettings({
|
||||
secretKey: e.target.value
|
||||
}))
|
||||
}
|
||||
|
||||
secretKeyVisible(secretKeyVisible) {
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.setSettings({
|
||||
secretKeyVisible
|
||||
}))
|
||||
}
|
||||
|
||||
// Save the auth params and set them.
|
||||
setAuth(e) {
|
||||
e.preventDefault()
|
||||
const {web, dispatch} = this.props
|
||||
|
||||
let accessKey = document.getElementById('accessKey').value
|
||||
let secretKey = document.getElementById('secretKey').value
|
||||
web.SetAuth({
|
||||
accessKey,
|
||||
secretKey
|
||||
})
|
||||
.then(data => {
|
||||
dispatch(actions.setSettings({
|
||||
accessKey: '',
|
||||
secretKey: '',
|
||||
secretKeyVisible: false
|
||||
}))
|
||||
dispatch(actions.hideSettings())
|
||||
dispatch(actions.showAlert({
|
||||
type: 'success',
|
||||
message: 'Changed credentials'
|
||||
}))
|
||||
})
|
||||
.catch(err => {
|
||||
dispatch(actions.setSettings({
|
||||
accessKey: '',
|
||||
secretKey: '',
|
||||
secretKeyVisible: false
|
||||
}))
|
||||
dispatch(actions.hideSettings())
|
||||
dispatch(actions.showAlert({
|
||||
type: 'danger',
|
||||
message: err.message
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
generateAuth(e) {
|
||||
e.preventDefault()
|
||||
const {dispatch} = this.props
|
||||
|
||||
web.GenerateAuth()
|
||||
.then(data => {
|
||||
dispatch(actions.setSettings({
|
||||
secretKeyVisible: true
|
||||
}))
|
||||
dispatch(actions.setSettings({
|
||||
accessKey: data.accessKey,
|
||||
secretKey: data.secretKey
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
hideSettings(e) {
|
||||
e.preventDefault()
|
||||
|
||||
const {dispatch} = this.props
|
||||
dispatch(actions.hideSettings())
|
||||
}
|
||||
|
||||
render() {
|
||||
let {settings} = this.props
|
||||
|
||||
return (
|
||||
<Modal bsSize="sm" animation={ false } show={ true }>
|
||||
<ModalHeader>
|
||||
Change Password
|
||||
</ModalHeader>
|
||||
<ModalBody className="m-t-20">
|
||||
<InputGroup value={ settings.accessKey }
|
||||
onChange={ this.accessKeyChange.bind(this) }
|
||||
id="accessKey"
|
||||
label="Access Key"
|
||||
name="accesskey"
|
||||
type="text"
|
||||
spellCheck="false"
|
||||
required="required"
|
||||
autoComplete="false"
|
||||
align="ig-left"
|
||||
readonly={ settings.keysReadOnly }></InputGroup>
|
||||
<i onClick={ this.secretKeyVisible.bind(this, !settings.secretKeyVisible) } className={ "toggle-password fa fa-eye " + (settings.secretKeyVisible ? "toggled" : "") } />
|
||||
<InputGroup value={ settings.secretKey }
|
||||
onChange={ this.secretKeyChange.bind(this) }
|
||||
id="secretKey"
|
||||
label="Secret Key"
|
||||
name="accesskey"
|
||||
type={ settings.secretKeyVisible ? "text" : "password" }
|
||||
spellCheck="false"
|
||||
required="required"
|
||||
autoComplete="false"
|
||||
align="ig-left"
|
||||
readonly={ settings.keysReadOnly }></InputGroup>
|
||||
</ModalBody>
|
||||
<div className="modal-footer">
|
||||
<button className={ "btn btn-primary " + (settings.keysReadOnly ? "hidden" : "") } onClick={ this.generateAuth.bind(this) }>
|
||||
Generate
|
||||
</button>
|
||||
<button href="" className={ "btn btn-success " + (settings.keysReadOnly ? "hidden" : "") } onClick={ this.setAuth.bind(this) }>
|
||||
Update
|
||||
</button>
|
||||
<button href="" className="btn btn-link" onClick={ this.hideSettings.bind(this) }>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(state => {
|
||||
return {
|
||||
web: state.web,
|
||||
settings: state.settings,
|
||||
serverInfo: state.serverInfo
|
||||
}
|
||||
})(SettingsModal)
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import classNames from 'classnames'
|
||||
import ClickOutHandler from 'react-onclickout'
|
||||
import Scrollbars from 'react-custom-scrollbars/lib/Scrollbars'
|
||||
import connect from 'react-redux/lib/components/connect'
|
||||
|
||||
import logo from '../../img/logo.svg'
|
||||
|
||||
let SideBar = ({visibleBuckets, loadBucket, currentBucket, selectBucket, searchBuckets, sidebarStatus, clickOutside, showPolicy}) => {
|
||||
|
||||
const list = visibleBuckets.map((bucket, i) => {
|
||||
return <li className={ classNames({
|
||||
'active': bucket === currentBucket
|
||||
}) } key={ i } onClick={ (e) => selectBucket(e, bucket) }>
|
||||
<a href="" className={ classNames({
|
||||
'fesli-loading': bucket === loadBucket
|
||||
}) }>
|
||||
{ bucket }
|
||||
</a>
|
||||
<i className="fesli-trigger" onClick={ showPolicy }></i>
|
||||
</li>
|
||||
})
|
||||
|
||||
return (
|
||||
<ClickOutHandler onClickOut={ clickOutside }>
|
||||
<div className={ classNames({
|
||||
'fe-sidebar': true,
|
||||
'toggled': sidebarStatus
|
||||
}) }>
|
||||
<div className="fes-header clearfix hidden-sm hidden-xs">
|
||||
<img src={ logo } alt="" />
|
||||
<h2>Minio Browser</h2>
|
||||
</div>
|
||||
<div className="fes-list">
|
||||
<div className="input-group ig-dark ig-left ig-search" style={ { display: web.LoggedIn() ? 'block' : 'none' } }>
|
||||
<input className="ig-text"
|
||||
type="text"
|
||||
onChange={ searchBuckets }
|
||||
placeholder="Search Buckets..." />
|
||||
<i className="ig-helpers"></i>
|
||||
</div>
|
||||
<div className="fesl-inner">
|
||||
<Scrollbars renderScrollbarVertical={ props => <div className="scrollbar-vertical" /> }>
|
||||
<ul>
|
||||
{ list }
|
||||
</ul>
|
||||
</Scrollbars>
|
||||
</div>
|
||||
</div>
|
||||
<div className="fes-host">
|
||||
<i className="fa fa-globe"></i>
|
||||
<a href="/">
|
||||
{ window.location.host }
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</ClickOutHandler>
|
||||
)
|
||||
}
|
||||
|
||||
// Subscribe it to state changes that affect only the sidebar.
|
||||
export default connect(state => {
|
||||
return {
|
||||
visibleBuckets: state.visibleBuckets,
|
||||
loadBucket: state.loadBucket,
|
||||
currentBucket: state.currentBucket,
|
||||
sidebarStatus: state.sidebarStatus
|
||||
}
|
||||
})(SideBar)
|
||||
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react'
|
||||
import humanize from 'humanize'
|
||||
import classNames from 'classnames'
|
||||
import connect from 'react-redux/lib/components/connect'
|
||||
|
||||
import ProgressBar from 'react-bootstrap/lib/ProgressBar'
|
||||
import ConfirmModal from './ConfirmModal'
|
||||
|
||||
import * as actions from '../actions'
|
||||
|
||||
// UploadModal is a modal that handles multiple file uploads.
|
||||
// During the upload, it displays a progress bar, and can transform into an
|
||||
// abort modal if the user decides to abort the uploads.
|
||||
class UploadModal extends React.Component {
|
||||
|
||||
// Abort all the current uploads.
|
||||
abortUploads(e) {
|
||||
e.preventDefault()
|
||||
const {dispatch, uploads} = this.props
|
||||
|
||||
for (var slug in uploads) {
|
||||
let upload = uploads[slug]
|
||||
upload.xhr.abort()
|
||||
dispatch(actions.stopUpload({
|
||||
slug
|
||||
}))
|
||||
}
|
||||
|
||||
this.hideAbort(e)
|
||||
}
|
||||
|
||||
// Show the abort modal instead of the progress modal.
|
||||
showAbort(e) {
|
||||
e.preventDefault()
|
||||
const {dispatch} = this.props
|
||||
|
||||
dispatch(actions.setShowAbortModal(true))
|
||||
}
|
||||
|
||||
// Show the progress modal instead of the abort modal.
|
||||
hideAbort(e) {
|
||||
e.preventDefault()
|
||||
const {dispatch} = this.props
|
||||
|
||||
dispatch(actions.setShowAbortModal(false))
|
||||
}
|
||||
|
||||
render() {
|
||||
const {uploads, showAbortModal} = this.props
|
||||
|
||||
// Show the abort modal.
|
||||
if (showAbortModal) {
|
||||
let baseClass = classNames({
|
||||
'abort-upload': true
|
||||
})
|
||||
let okIcon = classNames({
|
||||
'fa': true,
|
||||
'fa-times': true
|
||||
})
|
||||
let cancelIcon = classNames({
|
||||
'fa': true,
|
||||
'fa-cloud-upload': true
|
||||
})
|
||||
|
||||
return (
|
||||
<ConfirmModal show={ true }
|
||||
baseClass={ baseClass }
|
||||
text='Abort uploads in progress?'
|
||||
icon='fa fa-info-circle mci-amber'
|
||||
sub='This cannot be undone!'
|
||||
okText='Abort'
|
||||
okIcon={ okIcon }
|
||||
cancelText='Upload'
|
||||
cancelIcon={ cancelIcon }
|
||||
okHandler={ this.abortUploads.bind(this) }
|
||||
cancelHandler={ this.hideAbort.bind(this) }>
|
||||
</ConfirmModal>
|
||||
)
|
||||
}
|
||||
|
||||
// If we don't have any files uploading, don't show anything.
|
||||
let numberUploading = Object.keys(uploads).length
|
||||
if (numberUploading == 0)
|
||||
return ( <noscript></noscript> )
|
||||
|
||||
let totalLoaded = 0
|
||||
let totalSize = 0
|
||||
|
||||
// Iterate over each upload, adding together the total size and that
|
||||
// which has been uploaded.
|
||||
for (var slug in uploads) {
|
||||
let upload = uploads[slug]
|
||||
totalLoaded += upload.loaded
|
||||
totalSize += upload.size
|
||||
}
|
||||
|
||||
let percent = (totalLoaded / totalSize) * 100
|
||||
|
||||
// If more than one: "Uploading files (5)..."
|
||||
// If only one: "Uploading myfile.txt..."
|
||||
let text = 'Uploading ' + (numberUploading == 1 ? `'${uploads[Object.keys(uploads)[0]].name}'` : `files (${numberUploading})`) + '...'
|
||||
|
||||
return (
|
||||
<div className="alert alert-info progress animated fadeInUp ">
|
||||
<button type="button" className="close" onClick={ this.showAbort.bind(this) }>
|
||||
<span>×</span>
|
||||
</button>
|
||||
<div className="text-center">
|
||||
<small>{ text }</small>
|
||||
</div>
|
||||
<ProgressBar now={ percent } />
|
||||
<div className="text-center">
|
||||
<small>{ humanize.filesize(totalLoaded) } ({ percent.toFixed(2) } %)</small>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(state => {
|
||||
return {
|
||||
uploads: state.uploads,
|
||||
showAbortModal: state.showAbortModal
|
||||
}
|
||||
})(UploadModal)
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
import React from 'react'
|
||||
import ReactTestUtils, {renderIntoDocument} from 'react-addons-test-utils'
|
||||
|
||||
import expect from 'expect'
|
||||
import Login from '../Login'
|
||||
|
||||
describe('Login', () => {
|
||||
it('it should have empty credentials', () => {
|
||||
const alert = {
|
||||
show: false
|
||||
}
|
||||
const dispatch = () => {}
|
||||
let loginComponent = renderIntoDocument(<Login alert={alert} dispatch={dispatch} />)
|
||||
const accessKey = document.getElementById('accessKey')
|
||||
const secretKey = document.getElementById('secretKey')
|
||||
// Validate default value.
|
||||
expect(accessKey.value).toEqual('')
|
||||
expect(secretKey.value).toEqual('')
|
||||
})
|
||||
it('it should set accessKey and secretKey', () => {
|
||||
const alert = {
|
||||
show: false
|
||||
}
|
||||
const dispatch = () => {}
|
||||
let loginComponent = renderIntoDocument(<Login alert={alert} dispatch={dispatch} />)
|
||||
let accessKey = loginComponent.refs.accessKey
|
||||
let secretKey = loginComponent.refs.secretKey
|
||||
accessKey.value = 'demo-username'
|
||||
secretKey.value = 'demo-password'
|
||||
ReactTestUtils.Simulate.change(accessKey)
|
||||
ReactTestUtils.Simulate.change(secretKey)
|
||||
// Validate if the change has occurred.
|
||||
expect(loginComponent.refs.accessKey.value).toEqual('demo-username')
|
||||
expect(loginComponent.refs.secretKey.value).toEqual('demo-password')
|
||||
})
|
||||
});
|
||||
*/
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// File for all the browser constants.
|
||||
|
||||
// minioBrowserPrefix absolute path.
|
||||
export const minioBrowserPrefix = '/minio'
|
||||
export const READ_ONLY = 'readonly'
|
||||
export const WRITE_ONLY = 'writeonly'
|
||||
export const READ_WRITE = 'readwrite'
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import SuperAgent from 'superagent-es6-promise';
|
||||
import url from 'url'
|
||||
import Moment from 'moment'
|
||||
|
||||
export default class JSONrpc {
|
||||
constructor(params) {
|
||||
this.endpoint = params.endpoint
|
||||
this.namespace = params.namespace
|
||||
this.version = '2.0';
|
||||
const parsedUrl = url.parse(this.endpoint)
|
||||
this.host = parsedUrl.hostname
|
||||
this.path = parsedUrl.path
|
||||
this.port = parsedUrl.port
|
||||
|
||||
switch (parsedUrl.protocol) {
|
||||
case 'http:': {
|
||||
this.scheme = 'http'
|
||||
if (parsedUrl.port === 0) {
|
||||
this.port = 80
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'https:': {
|
||||
this.scheme = 'https'
|
||||
if (parsedUrl.port === 0) {
|
||||
this.port = 443
|
||||
}
|
||||
break
|
||||
}
|
||||
default: {
|
||||
throw new Error('Unknown protocol: ' + parsedUrl.protocol)
|
||||
}
|
||||
}
|
||||
}
|
||||
// call('Get', {id: NN, params: [...]}, function() {})
|
||||
call(method, options, token) {
|
||||
if (!options) {
|
||||
options = {}
|
||||
}
|
||||
if (!options.id) {
|
||||
options.id = 1;
|
||||
}
|
||||
if (!options.params) {
|
||||
options.params = {};
|
||||
}
|
||||
const dataObj = {
|
||||
id: options.id,
|
||||
jsonrpc: this.version,
|
||||
params: options.params ? options.params : {},
|
||||
method: this.namespace ? this.namespace + '.' + method : method
|
||||
}
|
||||
let requestParams = {
|
||||
host: this.host,
|
||||
port: this.port,
|
||||
path: this.path,
|
||||
scheme: this.scheme,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'x-amz-date': Moment().utc().format('YYYYMMDDTHHmmss') + 'Z'
|
||||
}
|
||||
}
|
||||
|
||||
if (token) {
|
||||
requestParams.headers.Authorization = 'Bearer ' + token
|
||||
}
|
||||
|
||||
let req = SuperAgent.post(this.endpoint)
|
||||
for (let key in requestParams.headers) {
|
||||
req.set(key, requestParams.headers[key])
|
||||
}
|
||||
// req.set('Access-Control-Allow-Origin', 'http://localhost:8080')
|
||||
return req.send(JSON.stringify(dataObj)).then(res => res)
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import mimedb from 'mime-types'
|
||||
|
||||
const isFolder = (name, contentType) => {
|
||||
if (name.endsWith('/')) return true
|
||||
return false
|
||||
}
|
||||
|
||||
const isPdf = (name, contentType) => {
|
||||
if (contentType === 'application/pdf') return true
|
||||
return false
|
||||
}
|
||||
|
||||
const isZip = (name, contentType) => {
|
||||
if (!contentType || !contentType.includes('/')) return false
|
||||
if (contentType.split('/')[1].includes('zip')) return true
|
||||
return false
|
||||
}
|
||||
|
||||
const isCode = (name, contentType) => {
|
||||
const codeExt = ['c', 'cpp', 'go', 'py', 'java', 'rb', 'js', 'pl', 'fs',
|
||||
'php', 'css', 'less', 'scss', 'coffee', 'net', 'html',
|
||||
'rs', 'exs', 'scala', 'hs', 'clj', 'el', 'scm', 'lisp',
|
||||
'asp', 'aspx']
|
||||
const ext = name.split('.').reverse()[0]
|
||||
for (var i in codeExt) {
|
||||
if (ext === codeExt[i]) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const isExcel = (name, contentType) => {
|
||||
if (!contentType || !contentType.includes('/')) return false
|
||||
const types = ['excel', 'spreadsheet']
|
||||
const subType = contentType.split('/')[1]
|
||||
for (var i in types) {
|
||||
if (subType.includes(types[i])) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const isDoc = (name, contentType) => {
|
||||
if (!contentType || !contentType.includes('/')) return false
|
||||
const types = ['word', '.document']
|
||||
const subType = contentType.split('/')[1]
|
||||
for (var i in types) {
|
||||
if (subType.includes(types[i])) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const isPresentation = (name, contentType) => {
|
||||
if (!contentType || !contentType.includes('/')) return false
|
||||
var types = ['powerpoint', 'presentation']
|
||||
const subType = contentType.split('/')[1]
|
||||
for (var i in types) {
|
||||
if (subType.includes(types[i])) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const typeToIcon = (type) => {
|
||||
return (name, contentType) => {
|
||||
if (!contentType || !contentType.includes('/')) return false
|
||||
if (contentType.split('/')[0] === type) return true
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
export const getDataType = (name, contentType) => {
|
||||
if (contentType === "") {
|
||||
contentType = mimedb.lookup(name) || 'application/octet-stream'
|
||||
}
|
||||
const check = [
|
||||
['folder', isFolder],
|
||||
['code', isCode],
|
||||
['audio', typeToIcon('audio')],
|
||||
['image', typeToIcon('image')],
|
||||
['video', typeToIcon('video')],
|
||||
['text', typeToIcon('text')],
|
||||
['pdf', isPdf],
|
||||
['zip', isZip],
|
||||
['excel', isExcel],
|
||||
['doc', isDoc],
|
||||
['presentation', isPresentation]
|
||||
]
|
||||
for (var i in check) {
|
||||
if (check[i][1](name, contentType)) return check[i][0]
|
||||
}
|
||||
return 'other'
|
||||
}
|
||||
@@ -1,206 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as actions from './actions'
|
||||
import { minioBrowserPrefix } from './constants'
|
||||
|
||||
export default (state = {
|
||||
buckets: [],
|
||||
visibleBuckets: [],
|
||||
objects: [],
|
||||
istruncated: true,
|
||||
storageInfo: {},
|
||||
serverInfo: {},
|
||||
currentBucket: '',
|
||||
currentPath: '',
|
||||
showMakeBucketModal: false,
|
||||
uploads: {},
|
||||
alert: {
|
||||
show: false,
|
||||
type: 'danger',
|
||||
message: ''
|
||||
},
|
||||
loginError: false,
|
||||
sortNameOrder: false,
|
||||
sortSizeOrder: false,
|
||||
sortDateOrder: false,
|
||||
latestUiVersion: currentUiVersion,
|
||||
sideBarActive: false,
|
||||
loginRedirectPath: minioBrowserPrefix,
|
||||
settings: {
|
||||
accessKey: '',
|
||||
secretKey: '',
|
||||
secretKeyVisible: false
|
||||
},
|
||||
showSettings: false,
|
||||
policies: [],
|
||||
deleteConfirmation: {
|
||||
object: '',
|
||||
show: false
|
||||
},
|
||||
shareObject: {
|
||||
show: false,
|
||||
url: '',
|
||||
object: ''
|
||||
},
|
||||
prefixWritable: false,
|
||||
checkedObjects: []
|
||||
}, action) => {
|
||||
let newState = Object.assign({}, state)
|
||||
switch (action.type) {
|
||||
case actions.SET_WEB:
|
||||
newState.web = action.web
|
||||
break
|
||||
case actions.SET_BUCKETS:
|
||||
newState.buckets = action.buckets
|
||||
break
|
||||
case actions.ADD_BUCKET:
|
||||
newState.buckets = [action.bucket, ...newState.buckets]
|
||||
newState.visibleBuckets = [action.bucket, ...newState.visibleBuckets]
|
||||
break
|
||||
case actions.SET_VISIBLE_BUCKETS:
|
||||
newState.visibleBuckets = action.visibleBuckets
|
||||
break
|
||||
case actions.SET_CURRENT_BUCKET:
|
||||
newState.currentBucket = action.currentBucket
|
||||
break
|
||||
case actions.APPEND_OBJECTS:
|
||||
newState.objects = [...newState.objects, ...action.objects]
|
||||
newState.marker = action.marker
|
||||
newState.istruncated = action.istruncated
|
||||
break
|
||||
case actions.SET_OBJECTS:
|
||||
newState.objects = [...action.objects]
|
||||
break
|
||||
case actions.RESET_OBJECTS:
|
||||
newState.objects = []
|
||||
newState.marker = ""
|
||||
newState.istruncated = false
|
||||
break
|
||||
case actions.SET_CURRENT_PATH:
|
||||
newState.currentPath = action.currentPath
|
||||
break
|
||||
case actions.SET_STORAGE_INFO:
|
||||
newState.storageInfo = action.storageInfo
|
||||
break
|
||||
case actions.SET_SERVER_INFO:
|
||||
newState.serverInfo = action.serverInfo
|
||||
break
|
||||
case actions.SHOW_MAKEBUCKET_MODAL:
|
||||
newState.showMakeBucketModal = action.showMakeBucketModal
|
||||
break
|
||||
case actions.UPLOAD_PROGRESS:
|
||||
newState.uploads = Object.assign({}, newState.uploads)
|
||||
newState.uploads[action.slug].loaded = action.loaded
|
||||
break
|
||||
case actions.ADD_UPLOAD:
|
||||
newState.uploads = Object.assign({}, newState.uploads, {
|
||||
[action.slug]: {
|
||||
loaded: 0,
|
||||
size: action.size,
|
||||
xhr: action.xhr,
|
||||
name: action.name
|
||||
}
|
||||
})
|
||||
break
|
||||
case actions.STOP_UPLOAD:
|
||||
newState.uploads = Object.assign({}, newState.uploads)
|
||||
delete newState.uploads[action.slug]
|
||||
break
|
||||
case actions.SET_ALERT:
|
||||
if (newState.alert.alertTimeout) clearTimeout(newState.alert.alertTimeout)
|
||||
if (!action.alert.show) {
|
||||
newState.alert = Object.assign({}, newState.alert, {
|
||||
show: false
|
||||
})
|
||||
} else {
|
||||
newState.alert = action.alert
|
||||
}
|
||||
break
|
||||
case actions.SET_LOGIN_ERROR:
|
||||
newState.loginError = true
|
||||
break
|
||||
case actions.SET_SHOW_ABORT_MODAL:
|
||||
newState.showAbortModal = action.showAbortModal
|
||||
break
|
||||
case actions.SHOW_ABOUT:
|
||||
newState.showAbout = action.showAbout
|
||||
break
|
||||
case actions.SET_SORT_NAME_ORDER:
|
||||
newState.sortNameOrder = action.sortNameOrder
|
||||
break
|
||||
case actions.SET_SORT_SIZE_ORDER:
|
||||
newState.sortSizeOrder = action.sortSizeOrder
|
||||
break
|
||||
case actions.SET_SORT_DATE_ORDER:
|
||||
newState.sortDateOrder = action.sortDateOrder
|
||||
break
|
||||
case actions.SET_LATEST_UI_VERSION:
|
||||
newState.latestUiVersion = action.latestUiVersion
|
||||
break
|
||||
case actions.SET_SIDEBAR_STATUS:
|
||||
newState.sidebarStatus = action.sidebarStatus
|
||||
break
|
||||
case actions.SET_LOGIN_REDIRECT_PATH:
|
||||
newState.loginRedirectPath = action.path
|
||||
case actions.SET_LOAD_BUCKET:
|
||||
newState.loadBucket = action.loadBucket
|
||||
break
|
||||
case actions.SET_LOAD_PATH:
|
||||
newState.loadPath = action.loadPath
|
||||
break
|
||||
case actions.SHOW_SETTINGS:
|
||||
newState.showSettings = action.showSettings
|
||||
break
|
||||
case actions.SET_SETTINGS:
|
||||
newState.settings = Object.assign({}, newState.settings, action.settings)
|
||||
break
|
||||
case actions.SHOW_BUCKET_POLICY:
|
||||
newState.showBucketPolicy = action.showBucketPolicy
|
||||
break
|
||||
case actions.SET_POLICIES:
|
||||
newState.policies = action.policies
|
||||
break
|
||||
case actions.DELETE_CONFIRMATION:
|
||||
newState.deleteConfirmation = Object.assign({}, action.payload)
|
||||
break
|
||||
case actions.SET_SHARE_OBJECT:
|
||||
newState.shareObject = Object.assign({}, action.shareObject)
|
||||
break
|
||||
case actions.SET_PREFIX_WRITABLE:
|
||||
newState.prefixWritable = action.prefixWritable
|
||||
break
|
||||
case actions.REMOVE_OBJECT:
|
||||
let idx = newState.objects.findIndex(object => object.name === action.object)
|
||||
if (idx == -1) break
|
||||
newState.objects = [...newState.objects.slice(0, idx), ...newState.objects.slice(idx + 1)]
|
||||
break
|
||||
|
||||
case actions.CHECKED_OBJECTS_ADD:
|
||||
newState.checkedObjects = [...newState.checkedObjects, action.objectName]
|
||||
break
|
||||
case actions.CHECKED_OBJECTS_REMOVE:
|
||||
let index = newState.checkedObjects.indexOf(action.objectName)
|
||||
if (index == -1) break
|
||||
newState.checkedObjects = [...newState.checkedObjects.slice(0, index), ...newState.checkedObjects.slice(index + 1)]
|
||||
break
|
||||
case actions.CHECKED_OBJECTS_RESET:
|
||||
newState.checkedObjects = []
|
||||
break
|
||||
}
|
||||
|
||||
return newState
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { minioBrowserPrefix } from './constants.js'
|
||||
|
||||
export const sortObjectsByName = (objects, order) => {
|
||||
let folders = objects.filter(object => object.name.endsWith('/'))
|
||||
let files = objects.filter(object => !object.name.endsWith('/'))
|
||||
folders = folders.sort((a, b) => {
|
||||
if (a.name.toLowerCase() < b.name.toLowerCase()) return -1
|
||||
if (a.name.toLowerCase() > b.name.toLowerCase()) return 1
|
||||
return 0
|
||||
})
|
||||
files = files.sort((a, b) => {
|
||||
if (a.name.toLowerCase() < b.name.toLowerCase()) return -1
|
||||
if (a.name.toLowerCase() > b.name.toLowerCase()) return 1
|
||||
return 0
|
||||
})
|
||||
if (order) {
|
||||
folders = folders.reverse()
|
||||
files = files.reverse()
|
||||
}
|
||||
return [...folders, ...files]
|
||||
}
|
||||
|
||||
export const sortObjectsBySize = (objects, order) => {
|
||||
let folders = objects.filter(object => object.name.endsWith('/'))
|
||||
let files = objects.filter(object => !object.name.endsWith('/'))
|
||||
files = files.sort((a, b) => a.size - b.size)
|
||||
if (order)
|
||||
files = files.reverse()
|
||||
return [...folders, ...files]
|
||||
}
|
||||
|
||||
export const sortObjectsByDate = (objects, order) => {
|
||||
let folders = objects.filter(object => object.name.endsWith('/'))
|
||||
let files = objects.filter(object => !object.name.endsWith('/'))
|
||||
files = files.sort((a, b) => new Date(a.lastModified).getTime() - new Date(b.lastModified).getTime())
|
||||
if (order)
|
||||
files = files.reverse()
|
||||
return [...folders, ...files]
|
||||
}
|
||||
|
||||
export const pathSlice = (path) => {
|
||||
path = path.replace(minioBrowserPrefix, '')
|
||||
let prefix = ''
|
||||
let bucket = ''
|
||||
if (!path) return {
|
||||
bucket,
|
||||
prefix
|
||||
}
|
||||
let objectIndex = path.indexOf('/', 1)
|
||||
if (objectIndex == -1) {
|
||||
bucket = path.slice(1)
|
||||
return {
|
||||
bucket,
|
||||
prefix
|
||||
}
|
||||
}
|
||||
bucket = path.slice(1, objectIndex)
|
||||
prefix = path.slice(objectIndex + 1)
|
||||
return {
|
||||
bucket,
|
||||
prefix
|
||||
}
|
||||
}
|
||||
|
||||
export const pathJoin = (bucket, prefix) => {
|
||||
if (!prefix)
|
||||
prefix = ''
|
||||
return minioBrowserPrefix + '/' + bucket + '/' + prefix
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { browserHistory } from 'react-router'
|
||||
import JSONrpc from './jsonrpc'
|
||||
import * as actions from './actions'
|
||||
import { minioBrowserPrefix } from './constants.js'
|
||||
import Moment from 'moment'
|
||||
import storage from 'local-storage-fallback'
|
||||
|
||||
export default class Web {
|
||||
constructor(endpoint, dispatch) {
|
||||
const namespace = 'Web'
|
||||
this.dispatch = dispatch
|
||||
this.JSONrpc = new JSONrpc({
|
||||
endpoint,
|
||||
namespace
|
||||
})
|
||||
}
|
||||
makeCall(method, options) {
|
||||
return this.JSONrpc.call(method, {
|
||||
params: options
|
||||
}, storage.getItem('token'))
|
||||
.catch(err => {
|
||||
if (err.status === 401) {
|
||||
storage.removeItem('token')
|
||||
browserHistory.push(`${minioBrowserPrefix}/login`)
|
||||
throw new Error('Please re-login.')
|
||||
}
|
||||
if (err.status)
|
||||
throw new Error(`Server returned error [${err.status}]`)
|
||||
throw new Error('Minio server is unreachable')
|
||||
})
|
||||
.then(res => {
|
||||
let json = JSON.parse(res.text)
|
||||
let result = json.result
|
||||
let error = json.error
|
||||
if (error) {
|
||||
throw new Error(error.message)
|
||||
}
|
||||
if (!Moment(result.uiVersion).isValid()) {
|
||||
throw new Error("Invalid UI version in the JSON-RPC response")
|
||||
}
|
||||
if (result.uiVersion !== currentUiVersion
|
||||
&& currentUiVersion !== 'MINIO_UI_VERSION') {
|
||||
storage.setItem('newlyUpdated', true)
|
||||
location.reload()
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
LoggedIn() {
|
||||
return !!storage.getItem('token')
|
||||
}
|
||||
Login(args) {
|
||||
return this.makeCall('Login', args)
|
||||
.then(res => {
|
||||
storage.setItem('token', `${res.token}`)
|
||||
return res
|
||||
})
|
||||
}
|
||||
Logout() {
|
||||
storage.removeItem('token')
|
||||
}
|
||||
ServerInfo() {
|
||||
return this.makeCall('ServerInfo')
|
||||
}
|
||||
StorageInfo() {
|
||||
return this.makeCall('StorageInfo')
|
||||
}
|
||||
ListBuckets() {
|
||||
return this.makeCall('ListBuckets')
|
||||
}
|
||||
MakeBucket(args) {
|
||||
return this.makeCall('MakeBucket', args)
|
||||
}
|
||||
ListObjects(args) {
|
||||
return this.makeCall('ListObjects', args)
|
||||
}
|
||||
PresignedGet(args) {
|
||||
return this.makeCall('PresignedGet', args)
|
||||
}
|
||||
PutObjectURL(args) {
|
||||
return this.makeCall('PutObjectURL', args)
|
||||
}
|
||||
RemoveObject(args) {
|
||||
return this.makeCall('RemoveObject', args)
|
||||
}
|
||||
GetAuth() {
|
||||
return this.makeCall('GetAuth')
|
||||
}
|
||||
GenerateAuth() {
|
||||
return this.makeCall('GenerateAuth')
|
||||
}
|
||||
SetAuth(args) {
|
||||
return this.makeCall('SetAuth', args)
|
||||
.then(res => {
|
||||
storage.setItem('token', `${res.token}`)
|
||||
return res
|
||||
})
|
||||
}
|
||||
GetBucketPolicy(args) {
|
||||
return this.makeCall('GetBucketPolicy', args)
|
||||
}
|
||||
SetBucketPolicy(args) {
|
||||
return this.makeCall('SetBucketPolicy', args)
|
||||
}
|
||||
ListAllBucketPolicies(args) {
|
||||
return this.makeCall('ListAllBucketPolicies', args)
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
.alert {
|
||||
border: 0;
|
||||
position: fixed;
|
||||
max-width: 500px;
|
||||
margin: 0;
|
||||
box-shadow: 0 4px 5px rgba(0, 0, 0, 0.1);
|
||||
color: @white;
|
||||
width: 100%;
|
||||
right: 20px;
|
||||
border-radius: 3px;
|
||||
padding: 17px 50px 17px 17px;
|
||||
z-index: 10010;
|
||||
.animation-duration(800ms);
|
||||
.animation-fill-mode(both);
|
||||
|
||||
&:not(.progress) {
|
||||
top: 20px;
|
||||
|
||||
@media(min-width: (@screen-sm-min)) {
|
||||
left: 50%;
|
||||
margin-left: -250px;
|
||||
}
|
||||
}
|
||||
|
||||
&.progress {
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
&.alert-danger {
|
||||
background: @red;
|
||||
}
|
||||
|
||||
&.alert-success {
|
||||
background: @green;
|
||||
}
|
||||
|
||||
&.alert-info {
|
||||
background: @blue;
|
||||
}
|
||||
|
||||
@media(max-width: (@screen-xs-max)) {
|
||||
left: 20px;
|
||||
width: ~"calc(100% - 40px)";
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin: 10px 10px 8px 0;
|
||||
height: 5px;
|
||||
box-shadow: none;
|
||||
border-radius: 1px;
|
||||
background-color: @blue;
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
box-shadow: none;
|
||||
background-color: @white;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
.animated{
|
||||
&.infinite {
|
||||
.animation-iteration-count(infinite);
|
||||
}
|
||||
}
|
||||
|
||||
@import 'fadeIn';
|
||||
@import 'fadeInDown';
|
||||
@import 'fadeInUp';
|
||||
@import 'fadeOut';
|
||||
@import 'fadeOutDown';
|
||||
@import 'fadeOutUp';
|
||||
@import 'zoomIn';
|
||||
@@ -1,26 +0,0 @@
|
||||
@-webkit-keyframes fadeIn {
|
||||
0% {opacity: 0;}
|
||||
100% {opacity: 1;}
|
||||
}
|
||||
|
||||
@-moz-keyframes fadeIn {
|
||||
0% {opacity: 0;}
|
||||
100% {opacity: 1;}
|
||||
}
|
||||
|
||||
@-o-keyframes fadeIn {
|
||||
0% {opacity: 0;}
|
||||
100% {opacity: 1;}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
0% {opacity: 0;}
|
||||
100% {opacity: 1;}
|
||||
}
|
||||
|
||||
.fadeIn {
|
||||
-webkit-animation-name: fadeIn;
|
||||
-moz-animation-name: fadeIn;
|
||||
-o-animation-name: fadeIn;
|
||||
animation-name: fadeIn;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
@-webkit-keyframes fadeInDown {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(-20px);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes fadeInDown {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-moz-transform: translateY(-20px);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
-moz-transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@-o-keyframes fadeInDown {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-ms-transform: translateY(-20px);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
-ms-transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInDown {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.fadeInDown {
|
||||
-webkit-animation-name: fadeInDown;
|
||||
-moz-animation-name: fadeInDown;
|
||||
-o-animation-name: fadeInDown;
|
||||
animation-name: fadeInDown;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
@-webkit-keyframes fadeInUp {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(20px);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes fadeInUp {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-moz-transform: translateY(20px);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
-moz-transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@-o-keyframes fadeInUp {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-o-transform: translateY(20px);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
-o-transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeInUp {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.fadeInUp {
|
||||
-webkit-animation-name: fadeInUp;
|
||||
-moz-animation-name: fadeInUp;
|
||||
-o-animation-name: fadeInUp;
|
||||
animation-name: fadeInUp;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
@-webkit-keyframes fadeOut {
|
||||
0% {opacity: 1;}
|
||||
100% {opacity: 0;}
|
||||
}
|
||||
|
||||
@-moz-keyframes fadeOut {
|
||||
0% {opacity: 1;}
|
||||
100% {opacity: 0;}
|
||||
}
|
||||
|
||||
@-o-keyframes fadeOut {
|
||||
0% {opacity: 1;}
|
||||
100% {opacity: 0;}
|
||||
}
|
||||
|
||||
@keyframes fadeOut {
|
||||
0% {opacity: 1;}
|
||||
100% {opacity: 0;}
|
||||
}
|
||||
|
||||
.fadeOut {
|
||||
-webkit-animation-name: fadeOut;
|
||||
-moz-animation-name: fadeOut;
|
||||
-o-animation-name: fadeOut;
|
||||
animation-name: fadeOut;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
@-webkit-keyframes fadeOutDown {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(20px);
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes fadeOutDown {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-moz-transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
-moz-transform: translateY(20px);
|
||||
}
|
||||
}
|
||||
|
||||
@-o-keyframes fadeOutDown {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-o-transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
-o-transform: translateY(20px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeOutDown {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
}
|
||||
|
||||
.fadeOutDown {
|
||||
-webkit-animation-name: fadeOutDown;
|
||||
-moz-animation-name: fadeOutDown;
|
||||
-o-animation-name: fadeOutDown;
|
||||
animation-name: fadeOutDown;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
@-webkit-keyframes fadeOutUp {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-webkit-transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: translateY(-20px);
|
||||
}
|
||||
}
|
||||
@-moz-keyframes fadeOutUp {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-moz-transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
-moz-transform: translateY(-20px);
|
||||
}
|
||||
}
|
||||
@-o-keyframes fadeOutUp {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-o-transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
-o-transform: translateY(-20px);
|
||||
}
|
||||
}
|
||||
@keyframes fadeOutUp {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateY(-20px);
|
||||
}
|
||||
}
|
||||
|
||||
.fadeOutUp {
|
||||
-webkit-animation-name: fadeOutUp;
|
||||
-moz-animation-name: fadeOutUp;
|
||||
-o-animation-name: fadeOutUp;
|
||||
animation-name: fadeOutUp;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
@-webkit-keyframes zoomIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(.3, .3, .3);
|
||||
transform: scale3d(.3, .3, .3);
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes zoomIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(.3, .3, .3);
|
||||
transform: scale3d(.3, .3, .3);
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
* {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: 10px;
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
a {
|
||||
.transition(color);
|
||||
.transition-duration(300ms);
|
||||
|
||||
}
|
||||
|
||||
button {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
.btn {
|
||||
border: 0;
|
||||
padding: 5px 10px;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
border-radius: 2px;
|
||||
text-align: center;
|
||||
.transition(all);
|
||||
.transition-duration(300ms);
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
.opacity(0.9);
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------
|
||||
Button Variants
|
||||
------------------------------------*/
|
||||
.btn-variant(@bg-color, @color) {
|
||||
color: @color;
|
||||
background-color: @bg-color;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: @color;
|
||||
background-color: darken(@bg-color, 6%);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.btn-block {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.btn-white {
|
||||
.btn-variant(#fff, darken(@text-color, 20%));
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
.btn-variant(#eee, #545454);
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
.btn-variant(@red, @white);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
.btn-variant(@blue, @white);
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
.btn-variant(@green, @white);
|
||||
}
|
||||
//-----------------------------------
|
||||
@@ -1,26 +0,0 @@
|
||||
.dropdown-menu {
|
||||
padding: 15px 0;
|
||||
top: 0;
|
||||
margin-top: -1px;
|
||||
|
||||
& > li {
|
||||
& > a {
|
||||
padding: 8px 20px;
|
||||
font-size: 15px;
|
||||
|
||||
& > i {
|
||||
width: 20px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu-right {
|
||||
& > li {
|
||||
& > a {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
/*------------------------------
|
||||
Layout
|
||||
--------------------------------*/
|
||||
.file-explorer {
|
||||
background-color: @white;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
|
||||
&.toggled {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.fe-body {
|
||||
@media(min-width: @screen-md-min) {
|
||||
padding: 0 0 40px @fe-sidebar-width;
|
||||
}
|
||||
|
||||
@media(max-width: @screen-sm-max) {
|
||||
padding: 75px 0 80px;
|
||||
}
|
||||
|
||||
min-height:100vh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------
|
||||
Create and Upload Button
|
||||
--------------------------------*/
|
||||
.feb-actions {
|
||||
position: fixed;
|
||||
bottom: 30px;
|
||||
right: 30px;
|
||||
|
||||
.dropdown-menu {
|
||||
min-width: 55px;
|
||||
width: 55px;
|
||||
text-align: center;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&.open {
|
||||
.feba-btn {
|
||||
.scale(1);
|
||||
|
||||
&:first-child {
|
||||
.animation-name(feba-btn-anim);
|
||||
.animation-duration(300ms);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
.animation-name(feba-btn-anim);
|
||||
.animation-duration(100ms);
|
||||
}
|
||||
}
|
||||
|
||||
.feba-toggle {
|
||||
background: darken(@red, 10%);
|
||||
|
||||
& > span {
|
||||
.rotate(135deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.feba-toggle {
|
||||
width: 55px;
|
||||
height: 55px;
|
||||
line-height: 55px;
|
||||
border-radius: 50%;
|
||||
background: @red;
|
||||
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.15);
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
i {
|
||||
color: @white;
|
||||
font-size: 17px;
|
||||
line-height: 58px;
|
||||
}
|
||||
}
|
||||
|
||||
.feba-toggle,
|
||||
.feba-toggle > span {
|
||||
.transition(all);
|
||||
.transition-duration(250ms);
|
||||
.backface-visibility(hidden);
|
||||
}
|
||||
|
||||
.feba-btn {
|
||||
width: 40px;
|
||||
margin-top: 10px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
color: @white;
|
||||
line-height: 40px;
|
||||
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.15);
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
position: relative;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
color: @white;
|
||||
}
|
||||
|
||||
label {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.feba-bucket {
|
||||
background: @orange;
|
||||
}
|
||||
|
||||
.feba-upload {
|
||||
background: @yellow;
|
||||
}
|
||||
|
||||
@-webkit-keyframes feba-btn-anim {
|
||||
from {
|
||||
.scale(0);
|
||||
.opacity(0);
|
||||
}
|
||||
to {
|
||||
.scale(1);
|
||||
.opacity(1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes feba-btn-anim {
|
||||
from {
|
||||
.scale(0);
|
||||
.opacity(0);
|
||||
}
|
||||
to {
|
||||
.scale(1);
|
||||
.opacity(1);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
@font-face {
|
||||
font-family: Lato;
|
||||
src: url('../../fonts/lato/lato-normal.woff2') format('woff2'),
|
||||
url('../../fonts/lato/lato-normal.woff') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
@@ -1,262 +0,0 @@
|
||||
.form-control {
|
||||
border: 0;
|
||||
border-bottom: 1px solid @input-border;
|
||||
color: #32393F;
|
||||
padding: 5px;
|
||||
width: 100%;
|
||||
font-size: 13px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
select.form-control {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
border-radius: 0;
|
||||
background: url(../../img/select-caret.svg) no-repeat bottom 7px right;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Input Group
|
||||
----------------------------*/
|
||||
.input-group {
|
||||
position: relative;
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
label:not(.ig-label) {
|
||||
font-size: 13px;
|
||||
display: block;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.ig-label {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
bottom: 7px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
.transition(all);
|
||||
.transition-duration(250ms);
|
||||
padding: 2px 0 3px;
|
||||
border-radius: 2px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.ig-helpers {
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
|
||||
&,
|
||||
&:before,
|
||||
&:after {
|
||||
position: absolute;
|
||||
height: 2px;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: '';
|
||||
width: 0;
|
||||
.transition(all);
|
||||
.transition-duration(250ms);
|
||||
background-color: #03A9F4;
|
||||
}
|
||||
|
||||
&:before {
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
&:after {
|
||||
right: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.ig-text {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
border: 0;
|
||||
background: transparent !important;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
border-bottom: 1px solid #eee;
|
||||
color: #32393F;
|
||||
font-size: 13px;
|
||||
|
||||
|
||||
&:focus + .ig-helpers {
|
||||
&:before,
|
||||
&:after {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
&:valid,
|
||||
&:disabled,
|
||||
&:focus {
|
||||
& ~ .ig-label {
|
||||
bottom: 35px;
|
||||
font-size: 13px;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
.opacity(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.ig-dark {
|
||||
.ig-text {
|
||||
color: @white !important;
|
||||
border-color: rgba(255,255,255,0.1) !important;
|
||||
}
|
||||
|
||||
.ig-helpers {
|
||||
&:before,
|
||||
&:after {
|
||||
background-color: #dfdfdf;
|
||||
height: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ig-left {
|
||||
.ig-label,
|
||||
.ig-text {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
.ig-error {
|
||||
.ig-label {
|
||||
color: #E23F3F;
|
||||
}
|
||||
.ig-helpers i {
|
||||
&:first-child,
|
||||
&:first-child:before,
|
||||
&:first-child:after {
|
||||
background: rgba(226, 63, 63, 0.43);
|
||||
}
|
||||
&:last-child,
|
||||
&:last-child:before,
|
||||
&:last-child:after {
|
||||
background: #E23F3F !important;
|
||||
}
|
||||
}
|
||||
&:after {
|
||||
content: "\f05a";
|
||||
font-family: FontAwesome;
|
||||
position: absolute;
|
||||
top: 17px;
|
||||
right: 9px;
|
||||
font-size: 20px;
|
||||
color: #D33D3E;
|
||||
}
|
||||
}
|
||||
|
||||
.ig-search {
|
||||
&:before {
|
||||
font-family: @font-family-icon;
|
||||
content: '\f002';
|
||||
font-size: 15px;
|
||||
position: absolute;
|
||||
left: 2px;
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
.ig-text {
|
||||
padding-left: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Share Spinners
|
||||
----------------------------*/
|
||||
.set-expire {
|
||||
border: 1px solid @input-border;
|
||||
margin: 35px 0 30px;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.set-expire-item {
|
||||
padding: 9px 5px 3px;
|
||||
position: relative;
|
||||
display: table-cell;
|
||||
width: 1%;
|
||||
text-align: center;
|
||||
.user-select(none);
|
||||
|
||||
&:not(:last-child) {
|
||||
border-right: 1px solid @input-border;
|
||||
}
|
||||
}
|
||||
|
||||
.set-expire-title {
|
||||
font-size: 10px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.set-expire-value {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
left: -8px;
|
||||
|
||||
input {
|
||||
.user-select(none);
|
||||
font-size: 20px;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
right: -15px;
|
||||
border: 0;
|
||||
color: @text-strong-color;
|
||||
padding: 0;
|
||||
height: 25px;
|
||||
width: 100%;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.set-expire-decrease,
|
||||
.set-expire-increase {
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: url(../../img/arrow.svg) no-repeat center;
|
||||
background-size: 85%;
|
||||
left: 50%;
|
||||
margin-left: -10px;
|
||||
.opacity(0.2);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
.opacity(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.set-expire-increase {
|
||||
top: -25px;
|
||||
}
|
||||
|
||||
.set-expire-decrease {
|
||||
bottom: -27px;
|
||||
.rotate(-180deg);
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*----------------------------
|
||||
Text Alignment
|
||||
-----------------------------*/
|
||||
.text-center { text-align: center !important; }
|
||||
.text-left { text-align: left !important; }
|
||||
.text-right { text-align: right !important; }
|
||||
|
||||
|
||||
/*----------------------------
|
||||
Float
|
||||
-----------------------------*/
|
||||
.clearfix { .clearfix(); }
|
||||
.pull-right { float: right !important; }
|
||||
.pull-left { float: left !important; }
|
||||
|
||||
|
||||
/*----------------------------
|
||||
Position
|
||||
-----------------------------*/
|
||||
.p-relative { position: relative; }
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Generate Margin Class
|
||||
margin, margin-top, margin-bottom, margin-left, margin-right
|
||||
----------------------------------------------------------------------------*/
|
||||
|
||||
.margin (@label, @size: 1, @key:1) when (@size =< 30){
|
||||
.m-@{key} {
|
||||
margin: @size !important;
|
||||
}
|
||||
|
||||
.m-t-@{key} {
|
||||
margin-top: @size !important;
|
||||
}
|
||||
|
||||
.m-b-@{key} {
|
||||
margin-bottom: @size !important;
|
||||
}
|
||||
|
||||
.m-l-@{key} {
|
||||
margin-left: @size !important;
|
||||
}
|
||||
|
||||
.m-r-@{key} {
|
||||
margin-right: @size !important;
|
||||
}
|
||||
|
||||
.margin(@label - 5; @size + 5; @key + 5);
|
||||
}
|
||||
|
||||
.margin(25, 0px, 0);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Generate Padding Class
|
||||
padding, padding-top, padding-bottom, padding-left, padding-right
|
||||
----------------------------------------------------------------------------*/
|
||||
.padding (@label, @size: 1, @key:1) when (@size =< 30){
|
||||
.p-@{key} {
|
||||
padding: @size !important;
|
||||
}
|
||||
|
||||
.p-t-@{key} {
|
||||
padding-top: @size !important;
|
||||
}
|
||||
|
||||
.p-b-@{key} {
|
||||
padding-bottom: @size !important;
|
||||
}
|
||||
|
||||
.p-l-@{key} {
|
||||
padding-left: @size !important;
|
||||
}
|
||||
|
||||
.p-r-@{key} {
|
||||
padding-right: @size !important;
|
||||
}
|
||||
|
||||
.padding(@label - 5; @size + 5; @key + 5);
|
||||
}
|
||||
|
||||
.padding(25, 0px, 0);
|
||||
@@ -1,240 +0,0 @@
|
||||
/*--------------------------
|
||||
Header
|
||||
----------------------------*/
|
||||
.fe-header {
|
||||
@media(min-width: (@screen-sm-min - 100)) {
|
||||
position: relative;
|
||||
padding: 40px 40px 20px 45px;
|
||||
}
|
||||
|
||||
@media(max-width: (@screen-xs-max - 100)) {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
|
||||
& > span {
|
||||
margin-bottom: 7px;
|
||||
display: inline-block;
|
||||
|
||||
&:not(:first-child) {
|
||||
&:before {
|
||||
content: '/';
|
||||
margin: 0 4px;
|
||||
color: @text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Disk usage
|
||||
----------------------------*/
|
||||
.feh-usage {
|
||||
margin-top: 12px;
|
||||
max-width: 285px;
|
||||
|
||||
@media(max-width: (@screen-xs-max - 100px)) {
|
||||
max-width: 100%;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
& > ul {
|
||||
margin-top: 7px;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
|
||||
& > li {
|
||||
padding-right: 0;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fehu-chart {
|
||||
height: 5px;
|
||||
background: #eee;
|
||||
position: relative;
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
|
||||
& > div {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
background: @link-color;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------
|
||||
Header Actions
|
||||
----------------------------*/
|
||||
.feh-actions {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
position: absolute;
|
||||
right: 35px;
|
||||
top: 30px;
|
||||
z-index: 11;
|
||||
|
||||
@media(max-width: (@screen-sm-max)) {
|
||||
top: 7px;
|
||||
right: 10px;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
& > li {
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
line-height: 100%;
|
||||
|
||||
& > a,
|
||||
& > .btn-group > button {
|
||||
display: block;
|
||||
height: 45px;
|
||||
min-width: 45px;
|
||||
text-align: center;
|
||||
border-radius: 50%;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: none;
|
||||
|
||||
@media(min-width: @screen-md-min) {
|
||||
color: #7B7B7B;
|
||||
font-size: 21px;
|
||||
line-height: 45px;
|
||||
.transition(all);
|
||||
.transition-duration(300ms);
|
||||
|
||||
&:hover {
|
||||
background: rgba(0,0,0,0.09);
|
||||
}
|
||||
}
|
||||
|
||||
@media(max-width: (@screen-sm-max)) {
|
||||
background: url(../../img/more-h-light.svg) no-repeat center;
|
||||
|
||||
.fa-reorder {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Mobile Header
|
||||
----------------------------*/
|
||||
@media(max-width: @screen-sm-max) {
|
||||
.fe-header-mobile {
|
||||
background-color: @dark-gray;
|
||||
padding: 10px 50px 9px 12px;
|
||||
text-align: center;
|
||||
position: fixed;
|
||||
z-index: 10;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.3);
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
|
||||
.mh-logo {
|
||||
height: 35px;
|
||||
position: relative;
|
||||
top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.feh-trigger {
|
||||
width: 41px;
|
||||
height: 41px;
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
|
||||
}
|
||||
|
||||
&:after {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&:before {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
.transition(all);
|
||||
.transition-duration(300ms);
|
||||
.scale(0);
|
||||
}
|
||||
}
|
||||
|
||||
.feht-toggled {
|
||||
&:before {
|
||||
.scale(1);
|
||||
}
|
||||
|
||||
.feht-lines {
|
||||
.rotate(180deg);
|
||||
|
||||
& > div {
|
||||
&.top {
|
||||
width: 12px;
|
||||
transform: translateX(8px) translateY(1px) rotate(45deg);
|
||||
-webkit-transform: translateX(8px) translateY(1px) rotate(45deg);
|
||||
}
|
||||
|
||||
&.bottom {
|
||||
width: 12px;
|
||||
transform: translateX(8px) translateY(-1px) rotate(-45deg);
|
||||
-webkit-transform: translateX(8px) translateY(-1px) rotate(-45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.feht-lines,
|
||||
.feht-lines > div {
|
||||
.transition(all);
|
||||
.transition-duration(300ms);
|
||||
}
|
||||
|
||||
.feht-lines {
|
||||
width: 18px;
|
||||
height: 12px;
|
||||
display: inline-block;
|
||||
margin-top: 14px;
|
||||
|
||||
& > div {
|
||||
background-color: #EAEAEA;
|
||||
width: 18px;
|
||||
height: 2px;
|
||||
|
||||
&.center {
|
||||
margin: 3px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
.ie-warning {
|
||||
background-color: #ff5252;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
text-align: center;
|
||||
|
||||
&:before {
|
||||
width: 1px;
|
||||
content: '';
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&:before,
|
||||
.iw-inner {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.iw-inner {
|
||||
width: 470px;
|
||||
height: 300px;
|
||||
background-color: @white;
|
||||
border-radius: 5px;
|
||||
padding: 40px;
|
||||
position: relative;
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 230px;
|
||||
margin-left: 80px;
|
||||
margin-top: 16px;
|
||||
|
||||
& > li {
|
||||
float: left;
|
||||
|
||||
& > a {
|
||||
display: block;
|
||||
padding: 10px 15px 7px;
|
||||
font-size: 14px;
|
||||
margin: 0 1px;
|
||||
border-radius: 3px;
|
||||
|
||||
&:hover {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 40px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.iwi-icon {
|
||||
color: #ff5252;
|
||||
font-size: 40px;
|
||||
display: block;
|
||||
line-height: 100%;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.iwi-skip {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: -35px;
|
||||
width: 100%;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: @white;
|
||||
}
|
||||
}
|
||||
@@ -1,486 +0,0 @@
|
||||
/*--------------------------
|
||||
Row
|
||||
----------------------------*/
|
||||
.fesl-row {
|
||||
position: relative;
|
||||
|
||||
@media (min-width: (@screen-sm-min - 100px)) {
|
||||
padding: 5px 20px 5px 40px;
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
@media(max-width: (@screen-xs-max - 100px)) {
|
||||
padding: 5px 20px;
|
||||
}
|
||||
|
||||
.clearfix();
|
||||
}
|
||||
|
||||
header.fesl-row {
|
||||
@media (min-width:(@screen-sm-min - 100px)) {
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 1px solid lighten(@text-muted-color, 20%);
|
||||
padding-left: 30px;
|
||||
|
||||
.fesl-item,
|
||||
.fesli-sort {
|
||||
.transition(all);
|
||||
.transition-duration(300ms);
|
||||
}
|
||||
|
||||
.fesl-item {
|
||||
cursor: pointer;
|
||||
color: @text-color;
|
||||
font-weight: 500;
|
||||
margin-bottom: -5px;
|
||||
|
||||
& > .fesli-sort {
|
||||
float: right;
|
||||
margin: 4px 0 0;
|
||||
.opacity(0);
|
||||
color: @dark-gray;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
&:hover:not(.fesl-item-actions) {
|
||||
background: lighten(@text-muted-color, 22%);
|
||||
color: @dark-gray;
|
||||
|
||||
& > .fesli-sort {
|
||||
.opacity(0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width:(@screen-xs-max - 100px)) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.list-type(@background, @icon) {
|
||||
.fis-icon {
|
||||
background-color: @background;
|
||||
|
||||
&:before {
|
||||
content: @icon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.fesl-row {
|
||||
border-bottom: 1px solid transparent;
|
||||
cursor: default;
|
||||
.transition(background-color);
|
||||
.transition-duration(500ms);
|
||||
|
||||
@media (max-width: (@screen-xs-max - 100px)) {
|
||||
padding: 5px 20px;
|
||||
}
|
||||
|
||||
&:not(.fesl-row-selected) {
|
||||
&:nth-child(even) {
|
||||
background-color: @list-row-even-bg;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.fis-icon {
|
||||
&:before {
|
||||
.opacity(0)
|
||||
}
|
||||
}
|
||||
|
||||
.fis-helper {
|
||||
&:before {
|
||||
.opacity(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------
|
||||
Icons
|
||||
----------------------------*/
|
||||
&[data-type=folder] { .list-type(#a1d6dd, '\f114'); }
|
||||
&[data-type=pdf] {.list-type(#fa7775, '\f1c1'); }
|
||||
&[data-type=zip] { .list-type(#427089, '\f1c6'); }
|
||||
&[data-type=audio] { .list-type(#009688, '\f1c7'); }
|
||||
&[data-type=code] { .list-type(#997867, "\f1c9"); }
|
||||
&[data-type=excel] { .list-type(#f1c3, '\f1c3'); }
|
||||
&[data-type=image] { .list-type(#f06292, '\f1c5'); }
|
||||
&[data-type=video] { .list-type(#f8c363, '\f1c8'); }
|
||||
&[data-type=other] { .list-type(#afafaf, '\f016'); }
|
||||
&[data-type=text] { .list-type(#8a8a8a, '\f0f6'); }
|
||||
&[data-type=doc] { .list-type(#2196f5, '\f1c2'); }
|
||||
&[data-type=presentation] { .list-type(#896ea6, '\f1c4'); }
|
||||
|
||||
&.fesl-loading{
|
||||
&:before {
|
||||
content: '';
|
||||
}
|
||||
|
||||
&:after {
|
||||
.list-loader(20px, 20px, rgba(255, 255, 255, 0.5), @white);
|
||||
left: 57px;
|
||||
top: 17px;
|
||||
|
||||
@media (max-width: (@screen-xs-max - 100px)) {
|
||||
left: 27px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.fesl-row-selected {
|
||||
background-color: @list-row-selected-bg;
|
||||
|
||||
&, .fesl-item a {
|
||||
color: darken(@text-color, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
.fi-select {
|
||||
float: left;
|
||||
position: relative;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
margin: 3px 0;
|
||||
|
||||
@media(max-width: (@screen-xs-max - 100px)) {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
input {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
z-index: 20;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
|
||||
&:checked {
|
||||
& ~ .fis-icon {
|
||||
background-color: #32393F;
|
||||
|
||||
&:before {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
& ~ .fis-helper {
|
||||
&:before {
|
||||
.scale(0);
|
||||
}
|
||||
|
||||
&:after {
|
||||
.scale(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fis-icon {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
border-radius: 50%;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
.transition(background-color);
|
||||
.transition-duration(250ms);
|
||||
|
||||
&:before {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
font-family: @font-family-icon;
|
||||
line-height: 35px;
|
||||
font-size: 16px;
|
||||
color: @white;
|
||||
.transition(all);
|
||||
.transition-duration(300ms);
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.fis-helper {
|
||||
&:before,
|
||||
&:after {
|
||||
position: absolute;
|
||||
.transition(all);
|
||||
.transition-duration(250ms);
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
border: 2px solid @white;
|
||||
z-index: 10;
|
||||
border-radius: 2px;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&:after {
|
||||
font-family: @font-family-icon;
|
||||
content: '\f00c';
|
||||
top: 8px;
|
||||
left: 9px;
|
||||
color: @white;
|
||||
font-size: 14px;
|
||||
.scale(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Files and Folders
|
||||
----------------------------*/
|
||||
.fesl-item {
|
||||
display: block;
|
||||
|
||||
a {
|
||||
color: darken(@text-color, 5%);
|
||||
}
|
||||
|
||||
@media(min-width: (@screen-sm-min - 100px)) {
|
||||
&:not(.fesl-item-actions):not(.fesl-item-icon) {
|
||||
text-overflow: ellipsis;
|
||||
padding: 10px 15px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&.fesl-item-name {
|
||||
flex: 3;
|
||||
}
|
||||
|
||||
&.fesl-item-size {
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
&.fesl-item-modified {
|
||||
width: 190px;
|
||||
}
|
||||
|
||||
&.fesl-item-actions {
|
||||
width: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@media(max-width: (@screen-xs-max - 100px)) {
|
||||
padding: 0;
|
||||
|
||||
&.fesl-item-name {
|
||||
width: 100%;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
&.fesl-item-size,
|
||||
&.fesl-item-modified {
|
||||
font-size: 12px;
|
||||
color: #B5B5B5;
|
||||
float: left;
|
||||
}
|
||||
|
||||
&.fesl-item-modified {
|
||||
max-width: 72px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&.fesl-item-size {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
&.fesl-item-actions {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Action buttons
|
||||
----------------------------*/
|
||||
.fia-toggle {
|
||||
height: 36px;
|
||||
width: 36px;
|
||||
background: transparent url(../../img/more-h.svg) no-repeat center;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
.opacity(0.4);
|
||||
|
||||
&:hover {
|
||||
.opacity(0.7);
|
||||
}
|
||||
}
|
||||
|
||||
.fesl-item-actions {
|
||||
.dropdown-menu {
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
padding: 0;
|
||||
right: 38px;
|
||||
left: auto;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
&.open {
|
||||
.dropdown-menu {
|
||||
.fiad-action {
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fiad-action {
|
||||
height: 35px;
|
||||
width: 35px;
|
||||
background: @amber;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
line-height: 35px;
|
||||
font-weight: normal;
|
||||
position: relative;
|
||||
top: 4px;
|
||||
margin-left: 5px;
|
||||
.animation-name(fiad-action-anim);
|
||||
.transform-origin(center center);
|
||||
.backface-visibility(none);
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
|
||||
&:nth-child(2) {
|
||||
.animation-duration(100ms);
|
||||
}
|
||||
|
||||
&:nth-child(1) {
|
||||
.animation-duration(250ms);
|
||||
}
|
||||
|
||||
& > i {
|
||||
font-size: 14px;
|
||||
color: @white;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: darken(@amber, 3%);
|
||||
}
|
||||
}
|
||||
|
||||
.list-actions {
|
||||
position: fixed;
|
||||
.translate3d(0, -100%, 0);
|
||||
.opacity(0);
|
||||
.transition(all);
|
||||
.transition-duration(200ms);
|
||||
padding: 20px 70px 20px 25px;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background-color: @brand-primary;
|
||||
z-index: 20;
|
||||
box-shadow: 0 0 10px rgba(0,0,0,0.3);
|
||||
text-align: center;
|
||||
|
||||
&.list-actions-toggled {
|
||||
.translate3d(0, 0, 0);
|
||||
.opacity(1);
|
||||
}
|
||||
}
|
||||
|
||||
.la-close {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 0;
|
||||
color: #fff;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
line-height: 30px !important;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
font-weight: normal;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.la-label {
|
||||
color: @white;
|
||||
float: left;
|
||||
padding: 4px 0;
|
||||
|
||||
.fa {
|
||||
font-size: 22px;
|
||||
vertical-align: top;
|
||||
margin-right: 10px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
}
|
||||
|
||||
.la-actions {
|
||||
button {
|
||||
background-color: transparent;
|
||||
border: 2px solid rgba(255,255,255,0.9);
|
||||
color: @white;
|
||||
border-radius: 2px;
|
||||
padding: 5px 10px;
|
||||
font-size: 13px;
|
||||
.transition(all);
|
||||
.transition-duration(300ms);
|
||||
margin-left: 10px;
|
||||
|
||||
&:hover {
|
||||
background-color: @white;
|
||||
color: @brand-primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes fiad-action-anim {
|
||||
from {
|
||||
.scale(0);
|
||||
.opacity(0);
|
||||
right: -20px;
|
||||
}
|
||||
to {
|
||||
.scale(1);
|
||||
.opacity(1);
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fiad-action-anim {
|
||||
from {
|
||||
.scale(0);
|
||||
.opacity(0);
|
||||
right: -20px;
|
||||
}
|
||||
to {
|
||||
.scale(1);
|
||||
.opacity(1);
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
.login {
|
||||
height: 100vh;
|
||||
min-height: 500px;
|
||||
background: @dark-gray;
|
||||
|
||||
text-align: center;
|
||||
&:before {
|
||||
height: ~"calc(100% - 110px)";
|
||||
width: 1px;
|
||||
content: "";
|
||||
}
|
||||
}
|
||||
|
||||
.l-wrap,
|
||||
.login:before {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.l-wrap {
|
||||
width: 80%;
|
||||
max-width: 500px;
|
||||
margin-top: -50px;
|
||||
&.toggled {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.input-group:not(:last-child) {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.l-footer {
|
||||
height: 110px;
|
||||
padding: 0 50px;
|
||||
}
|
||||
|
||||
.lf-logo {
|
||||
float: right;
|
||||
img {
|
||||
width: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.lf-server {
|
||||
float: left;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
padding-top: 40px;
|
||||
}
|
||||
|
||||
@media (max-width: @screen-sm-min) {
|
||||
.lf-logo,
|
||||
.lf-server {
|
||||
float: none;
|
||||
display: block;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.lf-logo {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.lf-server {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.lw-btn {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border: 1px solid @white;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
font-size: 22px;
|
||||
color: @white;
|
||||
.transition(all);
|
||||
.transition-duration(300ms);
|
||||
opacity: 0.3;
|
||||
background-color: transparent;
|
||||
line-height: 45px;
|
||||
padding: 0;
|
||||
&:hover {
|
||||
color: @white;
|
||||
opacity: 0.8;
|
||||
border-color: @white;
|
||||
}
|
||||
|
||||
i {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding-left: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------
|
||||
Chrome autofill fix
|
||||
-------------------------------*/
|
||||
input:-webkit-autofill {
|
||||
-webkit-box-shadow:0 0 0 50px @dark-gray inset !important;
|
||||
-webkit-text-fill-color: @white !important;
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
/*--------------------------
|
||||
Close
|
||||
----------------------------*/
|
||||
.close-variant(@color, @bg-color, @color-hover, @bg-color-hover) {
|
||||
span {
|
||||
background-color: @bg-color;
|
||||
color: @color;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
span {
|
||||
background-color: @bg-color-hover;
|
||||
color: @color-hover;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.close {
|
||||
right: 15px;
|
||||
font-weight: normal;
|
||||
opacity: 1;
|
||||
font-size: 18px;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
top: 16px;
|
||||
z-index: 1;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
|
||||
span {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
line-height: 24px;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
&:not(.close-alt) {
|
||||
.close-variant(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.1), @white, rgba(255, 255, 255, 0.2));
|
||||
}
|
||||
}
|
||||
|
||||
.close-alt {
|
||||
.close-variant(#989898, #efefef, #7b7b7b, #e8e8e8);
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Hidden
|
||||
----------------------------*/
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Copy text
|
||||
----------------------------*/
|
||||
.copy-text {
|
||||
input {
|
||||
width: 100%;
|
||||
border-radius: 1px;
|
||||
border: 1px solid @input-border;
|
||||
padding: 7px 12px;
|
||||
font-size: 13px;
|
||||
line-height: 100%;
|
||||
cursor: text;
|
||||
.transition(border-color);
|
||||
.transition-duration(300ms);
|
||||
|
||||
&:hover {
|
||||
border-color: darken(@input-border, 5%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------
|
||||
Sharing
|
||||
----------------------------*/
|
||||
.share-availability {
|
||||
margin-bottom: 40px;
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
position: absolute;
|
||||
bottom: -30px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: '01 Sec';
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '7 days';
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.modal-aheader {
|
||||
height: 100px;
|
||||
|
||||
&:before {
|
||||
height: 0 !important;
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
margin: 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*--------------------------
|
||||
User Select
|
||||
----------------------------*/
|
||||
.user-select(@value) {
|
||||
-webkit-user-select: @value;
|
||||
-moz-user-select: @value;
|
||||
-ms-user-select: @value;
|
||||
user-select: @value;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------
|
||||
CSS Animations based on animate.css
|
||||
-----------------------------------------*/
|
||||
.animated(@name, @duration) {
|
||||
-webkit-animation-name: @name;
|
||||
animation-name: @name;
|
||||
-webkit-animation-duration: @duration;
|
||||
animation-duration: @duration;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
For loop mixin for generate custom classes
|
||||
--------------------------------------------------*/
|
||||
.for(@i, @n) {.-each(@i)}
|
||||
.for(@n) when (isnumber(@n)) {.for(1, @n)}
|
||||
.for(@i, @n) when not (@i = @n) {
|
||||
.for((@i + (@n - @i) / abs(@n - @i)), @n);
|
||||
}
|
||||
|
||||
.for(@array) when (default()) {.for-impl_(length(@array))}
|
||||
.for-impl_(@i) when (@i > 1) {.for-impl_((@i - 1))}
|
||||
.for-impl_(@i) when (@i > 0) {.-each(extract(@array, @i))}
|
||||
|
||||
/*----------------------------------------
|
||||
List Loader
|
||||
-----------------------------------------*/
|
||||
.list-loader(@width, @height, @borderColor, @borderColorBottom) {
|
||||
content: '';
|
||||
width: @width;
|
||||
height: @height;
|
||||
border-radius: 50%;
|
||||
.animated(zoomIn, 500ms);
|
||||
border: 2px solid @borderColor;
|
||||
border-bottom-color: @borderColorBottom;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
-webkit-animation: zoomIn 250ms, spin 700ms 250ms infinite linear;
|
||||
animation: zoomIn 250ms, spin 700ms 250ms infinite linear;
|
||||
}
|
||||
@@ -1,294 +0,0 @@
|
||||
/*--------------------------
|
||||
Modal
|
||||
----------------------------*/
|
||||
.modal {
|
||||
@media(min-width: @screen-sm-min) {
|
||||
text-align: center;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
height: 100%;
|
||||
width: 1px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
text-align: left;
|
||||
margin: 10px auto;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal-dark {
|
||||
.modal-header {
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
|
||||
small {
|
||||
color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: @dark-gray;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-backdrop {
|
||||
.animated(fadeIn, 200ms);
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
.animated(zoomIn, 200ms);
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
color: @text-strong-color;
|
||||
position: relative;
|
||||
|
||||
small {
|
||||
display: block;
|
||||
text-transform: none;
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
color: #a8a8a8;
|
||||
}
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
border-radius: 3px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
padding: 0 30px 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Dialog
|
||||
----------------------------*/
|
||||
.modal-confirm {
|
||||
.modal-dialog {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.mc-icon {
|
||||
margin: 0 0 10px;
|
||||
|
||||
& > i {
|
||||
font-size: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
.mci-red {
|
||||
color: #ff8f8f;
|
||||
}
|
||||
|
||||
.mci-amber {
|
||||
color: @amber;
|
||||
}
|
||||
|
||||
.mci-green {
|
||||
color: #64e096;
|
||||
}
|
||||
|
||||
.mc-text {
|
||||
color: @text-strong-color;
|
||||
}
|
||||
|
||||
.mc-sub {
|
||||
color: @text-muted-color;
|
||||
margin-top: 5px;
|
||||
font-size: 13px;
|
||||
}
|
||||
//--------------------------
|
||||
|
||||
|
||||
/*--------------------------
|
||||
About
|
||||
----------------------------*/
|
||||
.modal-about {
|
||||
@media (max-width: @screen-xs-max) {
|
||||
text-align: center;
|
||||
|
||||
.modal-dialog {
|
||||
max-width: 400px;
|
||||
width: 90%;
|
||||
margin: 20px auto 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ma-inner {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
min-height: 350px;
|
||||
position: relative;
|
||||
|
||||
@media (min-width: @screen-sm-min) {
|
||||
&:before {
|
||||
content: '';
|
||||
width: 150px;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
border-radius: 3px 0 0px 3px;
|
||||
background-color: #23282C;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mai-item {
|
||||
&:first-child {
|
||||
width: 150px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
flex: 4;
|
||||
padding: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.maii-logo {
|
||||
width: 70px;
|
||||
position: relative;
|
||||
|
||||
}
|
||||
|
||||
.maii-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
|
||||
& > li {
|
||||
margin-bottom: 15px;
|
||||
|
||||
div {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
text-transform: uppercase;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 13px;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
}
|
||||
}
|
||||
//--------------------------
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Preferences
|
||||
----------------------------*/
|
||||
.toggle-password {
|
||||
position: absolute;
|
||||
bottom: 30px;
|
||||
right: 35px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 0;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
background-color: @white;
|
||||
padding-top: 5px;
|
||||
|
||||
&.toggled {
|
||||
background: #eee;
|
||||
}
|
||||
}
|
||||
//--------------------------
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Policy
|
||||
----------------------------*/
|
||||
.pm-body {
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
.pmb-header {
|
||||
margin-bottom: 35px;
|
||||
}
|
||||
|
||||
.pmb-list {
|
||||
display: flex;
|
||||
flex-flow: row nowrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px 35px;
|
||||
|
||||
&:nth-child(even) {
|
||||
background-color: #F7F7F7;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
header.pmb-list {
|
||||
margin: 20px 0 10px;
|
||||
}
|
||||
|
||||
.pmbl-item {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
|
||||
&:nth-child(1) {
|
||||
flex: 2;
|
||||
}
|
||||
|
||||
&:nth-child(2) {
|
||||
margin: 0 25px;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
&:nth-child(3) {
|
||||
width: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
div.pmb-list {
|
||||
select {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.pml-item {
|
||||
&:not(:last-child) {
|
||||
padding: 0 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
//--------------------------
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Create Bucket
|
||||
----------------------------*/
|
||||
.modal-create-bucket {
|
||||
.modal-dialog {
|
||||
position: fixed;
|
||||
right: 25px;
|
||||
bottom: 95px;
|
||||
margin: 0;
|
||||
height: 110px;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
//--------------------------
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
/*--------------------------
|
||||
Sidebar
|
||||
----------------------------*/
|
||||
.fe-sidebar {
|
||||
width: @fe-sidebar-width;
|
||||
background-color: @dark-gray;
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
padding: 25px;
|
||||
|
||||
@media(min-width: @screen-md-min) {
|
||||
.translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
@media(max-width: @screen-sm-max) {
|
||||
padding-top: 85px;
|
||||
z-index: 9;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.65);
|
||||
.transition(all);
|
||||
.transition-duration(300ms);
|
||||
.translate3d((-@fe-sidebar-width - 15px), 0, 0);
|
||||
|
||||
&.toggled {
|
||||
.translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgba(255, 255, 255, 0.58);
|
||||
|
||||
&:hover {
|
||||
color: @white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------
|
||||
Header
|
||||
----------------------------*/
|
||||
.fes-header {
|
||||
margin-bottom: 40px;
|
||||
|
||||
img,
|
||||
h2 {
|
||||
float: left;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 13px 0 0 10px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------
|
||||
List
|
||||
----------------------------*/
|
||||
.fesl-inner {
|
||||
height: ~"calc(100vh - 260px)";
|
||||
overflow: auto;
|
||||
padding: 0;
|
||||
margin: 0 -25px;
|
||||
|
||||
& li {
|
||||
position: relative;
|
||||
|
||||
& > a {
|
||||
display: block;
|
||||
padding: 10px 45px 12px 55px;
|
||||
word-wrap: break-word;
|
||||
|
||||
&:before {
|
||||
font-family: FontAwesome;
|
||||
content: '\f0a0';
|
||||
font-size: 17px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 25px;
|
||||
.opacity(0.8);
|
||||
}
|
||||
|
||||
&.fesli-loading {
|
||||
&:before {
|
||||
.list-loader(20px, 20px, rgba(255, 255, 255, 0.1), rgba(255, 255, 255, 0.5));
|
||||
left: 32px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: #282e32;
|
||||
|
||||
& > a {
|
||||
color: @white;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.active):hover {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
|
||||
& > a {
|
||||
color: @white;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.fesli-trigger {
|
||||
.opacity(0.6);
|
||||
|
||||
&:hover {
|
||||
.opacity(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&:hover .scrollbar-vertical {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.fesli-trigger {
|
||||
.opacity(0);
|
||||
.transition(all);
|
||||
.transition-duration(200ms);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 35px;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
background: url(../../img/more-h-light.svg) no-repeat top 20px left;
|
||||
}
|
||||
|
||||
/* Scrollbar */
|
||||
.scrollbar-vertical {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
.transition(opacity);
|
||||
.transition-duration(300ms);
|
||||
|
||||
div {
|
||||
border-radius: 1px !important;
|
||||
background-color: #6a6a6a !important;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------
|
||||
Host
|
||||
----------------------------*/
|
||||
.fes-host {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
background: @dark-gray;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
width: @fe-sidebar-width;
|
||||
padding: 20px;
|
||||
.text-overflow();
|
||||
|
||||
& > i {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
/*--------------------------
|
||||
Base
|
||||
----------------------------*/
|
||||
@font-family-sans-serif : 'Lato', sans-serif;
|
||||
@font-family-icon : 'fontAwesome';
|
||||
@body-bg : #edecec;
|
||||
@text-color : #8e8e8e;
|
||||
@font-size-base : 15px;
|
||||
@link-color : #46a5e0;
|
||||
@link-hover-decoration : none;
|
||||
|
||||
|
||||
/*--------------------------
|
||||
File Explorer
|
||||
----------------------------*/
|
||||
@fe-sidebar-width : 320px;
|
||||
@text-muted-color : #BDBDBD;
|
||||
@text-strong-color : #333;
|
||||
|
||||
/*--------------------------
|
||||
Colors
|
||||
----------------------------*/
|
||||
@cyan : #2ED2FF;
|
||||
@amber : #ffc107;
|
||||
@red : #ff726f;
|
||||
@grey : #f5f5f5;
|
||||
@dark-blue : #0084d3;
|
||||
@blue : #00a6f7;
|
||||
@white : #ffffff;
|
||||
@black : #1b1e25;
|
||||
@blue : #50b2ff;
|
||||
@light-blue : #c1d1e8;
|
||||
@green : #33d46f;
|
||||
@yellow : #FFC107;
|
||||
@orange : #ffc155;
|
||||
@purple : #9C27B0;
|
||||
@teal : #009688;
|
||||
@brown : #795548;
|
||||
@blue-gray : #374952;
|
||||
@dark-gray : #32393F;
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Dropdown
|
||||
----------------------------*/
|
||||
@dropdown-fallback-border : transparent;
|
||||
@dropdown-border : transparent;
|
||||
@dropdown-divider-bg : '';
|
||||
@dropdown-link-hover-bg : rgba(0,0,0,0.05);
|
||||
@dropdown-link-color : @text-color;
|
||||
@dropdown-link-hover-color : #333;
|
||||
@dropdown-link-disabled-color : #e4e4e4;
|
||||
@dropdown-divider-bg : rgba(0,0,0,0.08);
|
||||
@dropdown-link-active-color : #333;
|
||||
@dropdown-link-active-bg : rgba(0, 0, 0, 0.075);
|
||||
@dropdown-shadow : 0 2px 10px rgba(0, 0, 0, 0.2);
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Modal
|
||||
----------------------------*/
|
||||
@modal-content-fallback-border-color: transparent;
|
||||
@modal-content-border-color: transparent;
|
||||
@modal-backdrop-bg: rgba(0,0,0,0.1);
|
||||
@modal-header-border-color: transparent;
|
||||
@modal-title-line-height: transparent;
|
||||
@modal-footer-border-color: transparent;
|
||||
@modal-inner-padding: 30px 35px;
|
||||
@modal-title-padding: 30px 35px 0px;
|
||||
@modal-sm: 400px;
|
||||
|
||||
|
||||
/*-------------------------
|
||||
Buttons
|
||||
--------------------------*/
|
||||
@btn-border-radius-large: 2px;
|
||||
@btn-border-radius-small: 2px;
|
||||
@btn-border-radius-base: 2px;
|
||||
|
||||
|
||||
/*-------------------------
|
||||
Colors
|
||||
--------------------------*/
|
||||
@brand-primary: #2298f7;
|
||||
@brand-success: #4CAF50;
|
||||
@brand-info: #00BCD4;
|
||||
@brand-warning: #FF9800;
|
||||
@brand-danger: #FF5722;
|
||||
|
||||
|
||||
/*-------------------------
|
||||
Form
|
||||
--------------------------*/
|
||||
@input-border: #eee;
|
||||
|
||||
|
||||
/*-------------------------
|
||||
List
|
||||
--------------------------*/
|
||||
@list-row-selected-bg: #fbf2bf;
|
||||
@list-row-even-bg: #fafafa;
|
||||
@@ -1,39 +0,0 @@
|
||||
/*----------------------------
|
||||
Bootstrap
|
||||
-----------------------------*/
|
||||
@import "../../node_modules/bootstrap/less/scaffolding.less";
|
||||
@import "../../node_modules/bootstrap/less/variables.less";
|
||||
@import "../../node_modules/bootstrap/less/grid.less";
|
||||
@import "../../node_modules/bootstrap/less/mixins.less";
|
||||
@import "../../node_modules/bootstrap/less/normalize.less";
|
||||
@import "../../node_modules/bootstrap/less/dropdowns.less";
|
||||
@import "../../node_modules/bootstrap/less/modals.less";
|
||||
@import "../../node_modules/bootstrap/less/tooltip.less";
|
||||
@import "../../node_modules/bootstrap/less/responsive-utilities.less";
|
||||
|
||||
|
||||
/*----------------------------
|
||||
App
|
||||
-----------------------------*/
|
||||
@import 'inc/mixin';
|
||||
@import 'inc/variables';
|
||||
@import 'inc/base';
|
||||
@import 'inc/animate/animate';
|
||||
@import 'inc/generics';
|
||||
@import 'inc/font';
|
||||
@import 'inc/form';
|
||||
@import 'inc/buttons';
|
||||
@import 'inc/misc';
|
||||
@import 'inc/login';
|
||||
@import 'inc/header';
|
||||
@import 'inc/sidebar';
|
||||
@import 'inc/list';
|
||||
@import 'inc/file-explorer';
|
||||
@import 'inc/ie-warning';
|
||||
|
||||
/*----------------------------
|
||||
Boostrap
|
||||
-----------------------------*/
|
||||
@import 'inc/dropdown';
|
||||
@import 'inc/alert';
|
||||
@import 'inc/modal';
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var moment = require('moment')
|
||||
var async = require('async')
|
||||
var exec = require('child_process').exec
|
||||
var fs = require('fs')
|
||||
|
||||
var isProduction = process.env.NODE_ENV == 'production' ? true : false
|
||||
var assetsFileName = ''
|
||||
var commitId = ''
|
||||
var date = moment.utc()
|
||||
var version = date.format('YYYY-MM-DDTHH:mm:ss') + 'Z'
|
||||
var releaseTag = date.format('YYYY-MM-DDTHH-mm-ss') + 'Z'
|
||||
var buildType = 'DEVELOPMENT'
|
||||
if (process.env.MINIO_UI_BUILD) buildType = process.env.MINIO_UI_BUILD
|
||||
|
||||
rmDir = function(dirPath) {
|
||||
try { var files = fs.readdirSync(dirPath); }
|
||||
catch(e) { return; }
|
||||
if (files.length > 0)
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var filePath = dirPath + '/' + files[i];
|
||||
if (fs.statSync(filePath).isFile())
|
||||
fs.unlinkSync(filePath);
|
||||
else
|
||||
rmDir(filePath);
|
||||
}
|
||||
fs.rmdirSync(dirPath);
|
||||
};
|
||||
|
||||
async.waterfall([
|
||||
function(cb) {
|
||||
rmDir('production');
|
||||
rmDir('dev');
|
||||
var cmd = 'webpack -p --config webpack.production.config.js'
|
||||
if (!isProduction) {
|
||||
cmd = 'webpack';
|
||||
}
|
||||
console.log('Running', cmd)
|
||||
exec(cmd, cb)
|
||||
},
|
||||
function(stdout, stderr, cb) {
|
||||
if (isProduction) {
|
||||
fs.renameSync('production/index_bundle.js',
|
||||
'production/index_bundle-' + releaseTag + '.js')
|
||||
} else {
|
||||
fs.renameSync('dev/index_bundle.js',
|
||||
'dev/index_bundle-' + releaseTag + '.js')
|
||||
}
|
||||
var cmd = 'git log --format="%H" -n1'
|
||||
console.log('Running', cmd)
|
||||
exec(cmd, cb)
|
||||
},
|
||||
function(stdout, stderr, cb) {
|
||||
if (!stdout) throw new Error('commitId is empty')
|
||||
commitId = stdout.replace('\n', '')
|
||||
if (commitId.length !== 40) throw new Error('commitId invalid : ' + commitId)
|
||||
assetsFileName = 'ui-assets.go';
|
||||
var cmd = 'go-bindata-assetfs -pkg browser -nocompress=true production/...'
|
||||
if (!isProduction) {
|
||||
cmd = 'go-bindata-assetfs -pkg browser -nocompress=true dev/...'
|
||||
}
|
||||
console.log('Running', cmd)
|
||||
exec(cmd, cb)
|
||||
},
|
||||
function(stdout, stderr, cb) {
|
||||
var cmd = 'gofmt -s -w -l bindata_assetfs.go'
|
||||
console.log('Running', cmd)
|
||||
exec(cmd, cb)
|
||||
},
|
||||
function(stdout, stderr, cb) {
|
||||
fs.renameSync('bindata_assetfs.go', assetsFileName)
|
||||
fs.appendFileSync(assetsFileName, '\n')
|
||||
fs.appendFileSync(assetsFileName, 'var UIReleaseTag = "' + buildType + '.' +
|
||||
releaseTag + '"\n')
|
||||
fs.appendFileSync(assetsFileName, 'var UICommitID = "' + commitId + '"\n')
|
||||
fs.appendFileSync(assetsFileName, 'var UIVersion = "' + version + '"')
|
||||
fs.appendFileSync(assetsFileName, '\n')
|
||||
var contents;
|
||||
if (isProduction) {
|
||||
contents = fs.readFileSync(assetsFileName, 'utf8')
|
||||
.replace(/_productionIndexHtml/g, '_productionIndexHTML')
|
||||
.replace(/productionIndexHtmlBytes/g, 'productionIndexHTMLBytes')
|
||||
.replace(/productionIndexHtml/g, 'productionIndexHTML')
|
||||
.replace(/_productionIndex_bundleJs/g, '_productionIndexBundleJs')
|
||||
.replace(/productionIndex_bundleJsBytes/g, 'productionIndexBundleJsBytes')
|
||||
.replace(/productionIndex_bundleJs/g, 'productionIndexBundleJs')
|
||||
.replace(/_productionJqueryUiMinJs/g, '_productionJqueryUIMinJs')
|
||||
.replace(/productionJqueryUiMinJsBytes/g, 'productionJqueryUIMinJsBytes')
|
||||
.replace(/productionJqueryUiMinJs/g, 'productionJqueryUIMinJs');
|
||||
} else {
|
||||
contents = fs.readFileSync(assetsFileName, 'utf8')
|
||||
.replace(/_devIndexHtml/g, '_devIndexHTML')
|
||||
.replace(/devIndexHtmlBytes/g, 'devIndexHTMLBytes')
|
||||
.replace(/devIndexHtml/g, 'devIndexHTML')
|
||||
.replace(/_devIndex_bundleJs/g, '_devIndexBundleJs')
|
||||
.replace(/devIndex_bundleJsBytes/g, 'devIndexBundleJsBytes')
|
||||
.replace(/devIndex_bundleJs/g, 'devIndexBundleJs')
|
||||
.replace(/_devJqueryUiMinJs/g, '_devJqueryUIMinJs')
|
||||
.replace(/devJqueryUiMinJsBytes/g, 'devJqueryUIMinJsBytes')
|
||||
.replace(/devJqueryUiMinJs/g, 'devJqueryUIMinJs');
|
||||
}
|
||||
contents = contents.replace(/MINIO_UI_VERSION/g, version)
|
||||
contents = contents.replace(/index_bundle.js/g, 'index_bundle-' + releaseTag + '.js')
|
||||
|
||||
fs.writeFileSync(assetsFileName, contents, 'utf8')
|
||||
console.log('UI assets file :', assetsFileName)
|
||||
cb()
|
||||
}
|
||||
], function(err) {
|
||||
if (err) return console.log(err)
|
||||
})
|
||||
@@ -1,40 +0,0 @@
|
||||
var webpack = require('webpack');
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
browsers: [ process.env.CONTINUOUS_INTEGRATION ? 'Firefox' : 'Chrome' ],
|
||||
singleRun: true,
|
||||
frameworks: [ 'mocha' ],
|
||||
files: [
|
||||
'tests.webpack.js'
|
||||
],
|
||||
preprocessors: {
|
||||
'tests.webpack.js': [ 'webpack' ]
|
||||
},
|
||||
reporters: [ 'dots' ],
|
||||
webpack: {
|
||||
module: {
|
||||
loaders: [{
|
||||
test: /\.js$/,
|
||||
exclude: /(node_modules|bower_components)/,
|
||||
loader: 'babel',
|
||||
query: {
|
||||
presets: ['react', 'es2015']
|
||||
}
|
||||
}, {
|
||||
test: /\.less$/,
|
||||
loader: 'style!css!less'
|
||||
}, {
|
||||
test: /\.css$/,
|
||||
loader: 'style!css'
|
||||
}, {
|
||||
test: /\.(eot|woff|woff2|ttf|svg|png)/,
|
||||
loader: 'url'
|
||||
}]
|
||||
}
|
||||
},
|
||||
webpackServer: {
|
||||
noInfo: true
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -1,85 +0,0 @@
|
||||
{
|
||||
"name": "browser",
|
||||
"version": "0.0.1",
|
||||
"description": "Minio Browser",
|
||||
"scripts": {
|
||||
"test": "karma start",
|
||||
"dev": "NODE_ENV=dev webpack-dev-server --devtool eval --progress --colors --hot --content-base dev",
|
||||
"build": "NODE_ENV=dev node build.js",
|
||||
"release": "NODE_ENV=production MINIO_UI_BUILD=RELEASE node build.js",
|
||||
"format": "esformatter -i 'app/**/*.js'"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/minio/minio"
|
||||
},
|
||||
"author": "Minio Inc",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/minio/minio/issues"
|
||||
},
|
||||
"homepage": "https://github.com/minio/minio",
|
||||
"devDependencies": {
|
||||
"async": "^1.5.2",
|
||||
"babel-cli": "^6.14.0",
|
||||
"babel-core": "^6.14.0",
|
||||
"babel-loader": "^6.2.5",
|
||||
"babel-plugin-syntax-object-rest-spread": "^6.13.0",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.8.0",
|
||||
"babel-polyfill": "^6.23.0",
|
||||
"babel-preset-es2015": "^6.14.0",
|
||||
"babel-preset-react": "^6.11.1",
|
||||
"babel-register": "^6.14.0",
|
||||
"copy-webpack-plugin": "^0.3.3",
|
||||
"css-loader": "^0.23.1",
|
||||
"esformatter": "^0.10.0",
|
||||
"esformatter-jsx": "^7.4.1",
|
||||
"esformatter-jsx-ignore": "^1.0.6",
|
||||
"expect": "^1.20.2",
|
||||
"history": "^1.17.0",
|
||||
"html-webpack-plugin": "^2.22.0",
|
||||
"json-loader": "^0.5.4",
|
||||
"karma": "^0.13.22",
|
||||
"karma-chrome-launcher": "^0.2.3",
|
||||
"karma-cli": "^0.1.2",
|
||||
"karma-firefox-launcher": "^0.1.7",
|
||||
"karma-mocha": "^0.2.2",
|
||||
"karma-webpack": "^1.7.0",
|
||||
"less": "^2.7.1",
|
||||
"less-loader": "^2.2.3",
|
||||
"mocha": "^2.5.3",
|
||||
"moment": "^2.15.1",
|
||||
"purifycss-webpack-plugin": "^2.0.3",
|
||||
"react": "^0.14.8",
|
||||
"react-addons-test-utils": "^0.14.8",
|
||||
"react-bootstrap": "^0.28.5",
|
||||
"react-custom-scrollbars": "^2.3.0",
|
||||
"react-redux": "^4.4.5",
|
||||
"react-router": "^2.8.1",
|
||||
"redux": "^3.6.0",
|
||||
"redux-thunk": "^1.0.3",
|
||||
"style-loader": "^0.13.1",
|
||||
"superagent": "^1.8.4",
|
||||
"superagent-es6-promise": "^1.0.0",
|
||||
"url-loader": "^0.5.7",
|
||||
"webpack": "^1.12.11",
|
||||
"webpack-dev-server": "^1.14.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"bootstrap": "^3.3.6",
|
||||
"classnames": "^2.2.3",
|
||||
"font-awesome": "^4.7.0",
|
||||
"humanize": "0.0.9",
|
||||
"json-loader": "^0.5.4",
|
||||
"local-storage-fallback": "^1.3.0",
|
||||
"mime-db": "^1.25.0",
|
||||
"mime-types": "^2.1.13",
|
||||
"react": "^0.14.8",
|
||||
"react-copy-to-clipboard": "^4.2.3",
|
||||
"react-custom-scrollbars": "^2.2.2",
|
||||
"react-dom": "^0.14.6",
|
||||
"react-dropzone": "^3.5.3",
|
||||
"react-infinite-scroller": "^1.0.6",
|
||||
"react-onclickout": "2.0.4"
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
var context = require.context('./app', true, /-test\.js$/);
|
||||
context.keys().forEach(context);
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Minio Cloud Storage (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var webpack = require('webpack')
|
||||
var path = require('path')
|
||||
var CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||
var purify = require("purifycss-webpack-plugin")
|
||||
|
||||
var exports = {
|
||||
context: __dirname,
|
||||
entry: [
|
||||
path.resolve(__dirname, 'app/index.js')
|
||||
],
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dev'),
|
||||
filename: 'index_bundle.js',
|
||||
publicPath: '/minio/'
|
||||
},
|
||||
module: {
|
||||
loaders: [{
|
||||
test: /\.js$/,
|
||||
exclude: /(node_modules|bower_components)/,
|
||||
loader: 'babel',
|
||||
query: {
|
||||
presets: ['react', 'es2015']
|
||||
}
|
||||
}, {
|
||||
test: /\.less$/,
|
||||
loader: 'style!css!less'
|
||||
}, {
|
||||
test: /\.json$/,
|
||||
loader: 'json-loader'
|
||||
},{
|
||||
test: /\.css$/,
|
||||
loader: 'style!css'
|
||||
}, {
|
||||
test: /\.(eot|woff|woff2|ttf|svg|png)/,
|
||||
loader: 'url'
|
||||
}]
|
||||
},
|
||||
node:{
|
||||
fs:'empty'
|
||||
},
|
||||
devServer: {
|
||||
historyApiFallback: {
|
||||
index: '/minio/'
|
||||
},
|
||||
proxy: {
|
||||
'/minio/webrpc': {
|
||||
target: 'http://localhost:9000',
|
||||
secure: false
|
||||
},
|
||||
'/minio/upload/*': {
|
||||
target: 'http://localhost:9000',
|
||||
secure: false
|
||||
},
|
||||
'/minio/download/*': {
|
||||
target: 'http://localhost:9000',
|
||||
secure: false
|
||||
},
|
||||
'/minio/zip': {
|
||||
target: 'http://localhost:9000',
|
||||
secure: false
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new CopyWebpackPlugin([
|
||||
{from: 'app/css/loader.css'},
|
||||
{from: 'app/img/favicon.ico'},
|
||||
{from: 'app/img/browsers/chrome.png'},
|
||||
{from: 'app/img/browsers/firefox.png'},
|
||||
{from: 'app/img/browsers/safari.png'},
|
||||
{from: 'app/img/logo.svg'},
|
||||
{from: 'app/index.html'}
|
||||
]),
|
||||
new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/(en)$/),
|
||||
new purify({
|
||||
basePath: __dirname,
|
||||
paths: [
|
||||
"app/index.html",
|
||||
"app/js/*.js"
|
||||
]
|
||||
})
|
||||
]
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'dev') {
|
||||
exports.entry = [
|
||||
'webpack/hot/dev-server',
|
||||
'webpack-dev-server/client?http://localhost:8080',
|
||||
path.resolve(__dirname, 'app/index.js')
|
||||
]
|
||||
}
|
||||
|
||||
module.exports = exports
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Isomorphic Javascript library for Minio Browser JSON-RPC API, (C) 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var webpack = require('webpack')
|
||||
var path = require('path')
|
||||
var CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||
var purify = require("purifycss-webpack-plugin")
|
||||
|
||||
var exports = {
|
||||
context: __dirname,
|
||||
entry: [
|
||||
path.resolve(__dirname, 'app/index.js')
|
||||
],
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'production'),
|
||||
filename: 'index_bundle.js'
|
||||
},
|
||||
module: {
|
||||
loaders: [{
|
||||
test: /\.js$/,
|
||||
exclude: /(node_modules|bower_components)/,
|
||||
loader: 'babel',
|
||||
query: {
|
||||
presets: ['react', 'es2015']
|
||||
}
|
||||
}, {
|
||||
test: /\.less$/,
|
||||
loader: 'style!css!less'
|
||||
}, {
|
||||
test: /\.json$/,
|
||||
loader: 'json-loader'
|
||||
}, {
|
||||
test: /\.css$/,
|
||||
loader: 'style!css'
|
||||
}, {
|
||||
test: /\.(eot|woff|woff2|ttf|svg|png)/,
|
||||
loader: 'url'
|
||||
}]
|
||||
},
|
||||
node:{
|
||||
fs:'empty'
|
||||
},
|
||||
plugins: [
|
||||
new CopyWebpackPlugin([
|
||||
{from: 'app/css/loader.css'},
|
||||
{from: 'app/img/favicon.ico'},
|
||||
{from: 'app/img/browsers/chrome.png'},
|
||||
{from: 'app/img/browsers/firefox.png'},
|
||||
{from: 'app/img/browsers/safari.png'},
|
||||
{from: 'app/img/logo.svg'},
|
||||
{from: 'app/index.html'}
|
||||
]),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': '"production"'
|
||||
}),
|
||||
new webpack.ContextReplacementPlugin(/moment[\\\/]locale$/, /^\.\/(en)$/),
|
||||
new purify({
|
||||
basePath: __dirname,
|
||||
paths: [
|
||||
"app/index.html",
|
||||
"app/js/*.js"
|
||||
]
|
||||
})
|
||||
]
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'dev') {
|
||||
exports.entry = [
|
||||
'webpack/hot/dev-server',
|
||||
'webpack-dev-server/client?http://localhost:8080',
|
||||
path.resolve(__dirname, 'app/index.js')
|
||||
]
|
||||
}
|
||||
|
||||
module.exports = exports
|
||||
@@ -5,7 +5,7 @@ _init() {
|
||||
LDFLAGS=$(go run buildscripts/gen-ldflags.go)
|
||||
|
||||
# Extract release tag
|
||||
release_tag=$(echo $LDFLAGS | awk {'print $6'} | cut -f2 -d=)
|
||||
release_tag=$(echo $LDFLAGS | awk {'print $4'} | cut -f2 -d=)
|
||||
|
||||
# Verify release tag.
|
||||
if [ -z "$release_tag" ]; then
|
||||
@@ -23,12 +23,11 @@ _init() {
|
||||
fi
|
||||
|
||||
# List of supported architectures
|
||||
SUPPORTED_OSARCH='linux/386 linux/amd64 linux/arm linux/arm64 windows/386 windows/amd64 darwin/amd64 freebsd/amd64'
|
||||
SUPPORTED_OSARCH='linux/386 linux/amd64 linux/arm windows/386 windows/amd64 darwin/amd64 freebsd/amd64'
|
||||
|
||||
## System binaries
|
||||
CP=`which cp`
|
||||
SHASUM=`which shasum`
|
||||
SHA256SUM="${SHASUM} -a 256"
|
||||
SED=`which sed`
|
||||
}
|
||||
|
||||
@@ -44,19 +43,11 @@ go_build() {
|
||||
release_bin="$release_str/$os-$arch/$(basename $package).$release_tag"
|
||||
# Release binary downloadable name
|
||||
release_real_bin="$release_str/$os-$arch/$(basename $package)"
|
||||
|
||||
# Release sha1sum name
|
||||
release_shasum="$release_str/$os-$arch/$(basename $package).${release_tag}.shasum"
|
||||
# Release sha1sum default
|
||||
release_shasum_default="$release_str/$os-$arch/$(basename $package).shasum"
|
||||
|
||||
# Release sha256sum name
|
||||
release_sha256sum="$release_str/$os-$arch/$(basename $package).${release_tag}.sha256sum"
|
||||
# Release sha256sum default
|
||||
release_sha256sum_default="$release_str/$os-$arch/$(basename $package).sha256sum"
|
||||
# Release shasum name
|
||||
release_shasum="$release_str/$os-$arch/$(basename $package).shasum"
|
||||
|
||||
# Go build to build the binary.
|
||||
CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build --ldflags "${LDFLAGS}" -o $release_bin
|
||||
GOOS=$os GOARCH=$arch go build --ldflags "${LDFLAGS}" -o $release_bin
|
||||
|
||||
# Create copy
|
||||
if [ $os == "windows" ]; then
|
||||
@@ -65,15 +56,9 @@ go_build() {
|
||||
$CP -p $release_bin $release_real_bin
|
||||
fi
|
||||
|
||||
# Calculate sha1sum
|
||||
# Calculate shasum
|
||||
shasum_str=$(${SHASUM} ${release_bin})
|
||||
echo ${shasum_str} | $SED "s/$release_str\/$os-$arch\///g" > $release_shasum
|
||||
$CP -p $release_shasum $release_shasum_default
|
||||
|
||||
# Calculate sha256sum
|
||||
sha256sum_str=$(${SHA256SUM} ${release_bin})
|
||||
echo ${sha256sum_str} | $SED "s/$release_str\/$os-$arch\///g" > $release_sha256sum
|
||||
$CP -p $release_sha256sum $release_sha256sum_default
|
||||
}
|
||||
|
||||
main() {
|
||||
@@ -85,14 +70,12 @@ main() {
|
||||
done
|
||||
|
||||
read -p "If you want to build for all, Just press Enter: " chosen_osarch
|
||||
if [ "$chosen_osarch" = "" ] || [ "$chosen_osarch" = "all" ]; then
|
||||
if [ "$chosen_osarch" = "" ]; then
|
||||
for each_osarch in ${SUPPORTED_OSARCH}; do
|
||||
go_build ${each_osarch}
|
||||
done
|
||||
else
|
||||
for each_osarch in $(echo $chosen_osarch | sed 's/,/ /g'); do
|
||||
go_build ${each_osarch}
|
||||
done
|
||||
go_build ${chosen_osarch}
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Minio Cloud Storage, (C) 2014-2016 Minio, Inc.
|
||||
# Minio Cloud Storage, (C) 2015 Minio, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -21,26 +21,14 @@ _init() {
|
||||
|
||||
## Minimum required versions for build dependencies
|
||||
GIT_VERSION="1.0"
|
||||
GO_VERSION="1.7.1"
|
||||
GO_VERSION="1.6"
|
||||
OSX_VERSION="10.8"
|
||||
KNAME=$(uname -s)
|
||||
ARCH=$(uname -m)
|
||||
case "${KNAME}" in
|
||||
SunOS )
|
||||
ARCH=$(isainfo -k)
|
||||
;;
|
||||
esac
|
||||
UNAME=$(uname -sm)
|
||||
|
||||
## Check all dependencies are present
|
||||
MISSING=""
|
||||
}
|
||||
|
||||
## FIXME:
|
||||
## In OSX, 'readlink -f' option does not exist, hence
|
||||
## we have our own readlink -f behaviour here.
|
||||
## Once OSX has the option, below function is good enough.
|
||||
##
|
||||
## readlink() {
|
||||
## return /bin/readlink -f "$1"
|
||||
## }
|
||||
##
|
||||
readlink() {
|
||||
TARGET_FILE=$1
|
||||
|
||||
@@ -62,115 +50,172 @@ readlink() {
|
||||
echo $RESULT
|
||||
}
|
||||
|
||||
## FIXME:
|
||||
## In OSX, 'sort -V' option does not exist, hence
|
||||
## we have our own version compare function.
|
||||
## Once OSX has the option, below function is good enough.
|
||||
##
|
||||
## check_minimum_version() {
|
||||
## versions=($(echo -e "$1\n$2" | sort -V))
|
||||
## return [ "$1" == "${versions[0]}" ]
|
||||
## }
|
||||
##
|
||||
check_minimum_version() {
|
||||
IFS='.' read -r -a varray1 <<< "$1"
|
||||
IFS='.' read -r -a varray2 <<< "$2"
|
||||
###
|
||||
#
|
||||
# Takes two arguments
|
||||
# arg1: version number in `x.x.x` format
|
||||
# arg2: version number in `x.x.x` format
|
||||
#
|
||||
# example: check_version "$version1" "$version2"
|
||||
#
|
||||
# returns:
|
||||
# 0 - Installed version is equal to required
|
||||
# 1 - Installed version is greater than required
|
||||
# 2 - Installed version is lesser than required
|
||||
# 3 - If args have length zero
|
||||
#
|
||||
####
|
||||
check_version() {
|
||||
## validate args
|
||||
[[ -z "$1" ]] && return 3
|
||||
[[ -z "$2" ]] && return 3
|
||||
|
||||
if [[ $1 == $2 ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local IFS=.
|
||||
local i ver1=($1) ver2=($2)
|
||||
# fill empty fields in ver1 with zeros
|
||||
for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)); do
|
||||
ver1[i]=0
|
||||
done
|
||||
for ((i=0; i<${#ver1[@]}; i++)); do
|
||||
if [[ -z ${ver2[i]} ]]; then
|
||||
# fill empty fields in ver2 with zeros
|
||||
ver2[i]=0
|
||||
fi
|
||||
if ((10#${ver1[i]} > 10#${ver2[i]})); then
|
||||
|
||||
for i in "${!varray1[@]}"; do
|
||||
if [[ ${varray1[i]} -lt ${varray2[i]} ]]; then
|
||||
return 0
|
||||
elif [[ ${varray1[i]} -gt ${varray2[i]} ]]; then
|
||||
return 1
|
||||
fi
|
||||
if ((10#${ver1[i]} < 10#${ver2[i]})); then
|
||||
## Installed version is lesser than required - Bad condition
|
||||
return 2
|
||||
fi
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
assert_is_supported_arch() {
|
||||
case "${ARCH}" in
|
||||
x86_64 | amd64 | aarch64 | arm* )
|
||||
return
|
||||
;;
|
||||
*)
|
||||
echo "ERROR"
|
||||
echo "Arch '${ARCH}' not supported."
|
||||
echo "Supported Arch: [x86_64, amd64, aarch64, arm*]"
|
||||
exit 1
|
||||
esac
|
||||
}
|
||||
|
||||
assert_is_supported_os() {
|
||||
case "${KNAME}" in
|
||||
Linux | FreeBSD | OpenBSD | NetBSD | DragonFly | SunOS )
|
||||
return
|
||||
;;
|
||||
Darwin )
|
||||
osx_host_version=$(env sw_vers -productVersion)
|
||||
if ! check_minimum_version "${OSX_VERSION}" "${osx_host_version}"; then
|
||||
echo "ERROR"
|
||||
echo "OSX version '${osx_host_version}' not supported."
|
||||
echo "Minimum supported version: ${OSX_VERSION}"
|
||||
exit 1
|
||||
fi
|
||||
return
|
||||
;;
|
||||
*)
|
||||
echo "ERROR"
|
||||
echo "OS '${KNAME}' is not supported."
|
||||
echo "Supported OS: [Linux, FreeBSD, OpenBSD, NetBSD, Darwin, DragonFly]"
|
||||
exit 1
|
||||
esac
|
||||
}
|
||||
|
||||
assert_check_golang_env() {
|
||||
if ! which go >/dev/null 2>&1; then
|
||||
check_golang_env() {
|
||||
echo ${GOROOT:?} 2>&1 >/dev/null
|
||||
if [ $? -eq 1 ]; then
|
||||
echo "ERROR"
|
||||
echo "Cannot find go binary in your PATH configuration, please refer to Go installation document at"
|
||||
echo "https://docs.minio.io/docs/how-to-install-golang"
|
||||
echo "GOROOT environment variable missing, please refer to Go installation document"
|
||||
echo "https://github.com/minio/minio/blob/master/INSTALLGO.md#install-go-13"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
installed_go_version=$(go version | sed 's/^.* go\([0-9.]*\).*$/\1/')
|
||||
if ! check_minimum_version "${GO_VERSION}" "${installed_go_version}"; then
|
||||
echo "ERROR"
|
||||
echo "Go version '${installed_go_version}' not supported."
|
||||
echo "Minimum supported version: ${GO_VERSION}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "${GOPATH}" ]; then
|
||||
echo ${GOPATH:?} 2>&1 >/dev/null
|
||||
if [ $? -eq 1 ]; then
|
||||
echo "ERROR"
|
||||
echo "GOPATH environment variable missing, please refer to Go installation document"
|
||||
echo "https://docs.minio.io/docs/how-to-install-golang"
|
||||
echo "https://github.com/minio/minio/blob/master/INSTALLGO.md#install-go-13"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local go_binary_path=$(which go)
|
||||
|
||||
if [ -z "${go_binary_path}" ] ; then
|
||||
echo "Cannot find go binary in your PATH configuration, please refer to Go installation document"
|
||||
echo "https://github.com/minio/minio/blob/master/INSTALLGO.md#install-go-13"
|
||||
exit -1
|
||||
fi
|
||||
|
||||
local new_go_binary_path=${go_binary_path}
|
||||
if [ -h "${go_binary_path}" ]; then
|
||||
new_go_binary_path=$(readlink ${go_binary_path})
|
||||
fi
|
||||
|
||||
if [[ !"$(dirname ${new_go_binary_path})" =~ *"${GOROOT%%*(/)}"* ]] ; then
|
||||
echo "The go binary found in your PATH configuration does not belong to the Go installation pointed by your GOROOT environment," \
|
||||
"please refer to Go installation document"
|
||||
echo "https://github.com/minio/minio/blob/master/INSTALLGO.md#install-go-13"
|
||||
exit -1
|
||||
fi
|
||||
}
|
||||
|
||||
assert_check_deps() {
|
||||
# support unusual Git versions such as: 2.7.4 (Apple Git-66)
|
||||
installed_git_version=$(git version | perl -ne '$_ =~ m/git version (.*?)( |$)/; print "$1\n";')
|
||||
if ! check_minimum_version "${GIT_VERSION}" "${installed_git_version}"; then
|
||||
echo "ERROR"
|
||||
echo "Git version '${installed_git_version}' not supported."
|
||||
echo "Minimum supported version: ${GIT_VERSION}"
|
||||
exit 1
|
||||
is_supported_os() {
|
||||
case ${UNAME%% *} in
|
||||
"Linux")
|
||||
os="linux"
|
||||
;;
|
||||
"FreeBSD")
|
||||
os="freebsd"
|
||||
;;
|
||||
"Darwin")
|
||||
osx_host_version=$(env sw_vers -productVersion)
|
||||
check_version "${osx_host_version}" "${OSX_VERSION}"
|
||||
[[ $? -ge 2 ]] && die "Minimum OSX version supported is ${OSX_VERSION}"
|
||||
;;
|
||||
"*")
|
||||
echo "Exiting.. unsupported operating system found"
|
||||
exit 1;
|
||||
esac
|
||||
}
|
||||
|
||||
is_supported_arch() {
|
||||
local supported
|
||||
case ${UNAME##* } in
|
||||
"x86_64" | "amd64")
|
||||
supported=1
|
||||
;;
|
||||
"arm"*)
|
||||
supported=1
|
||||
;;
|
||||
*)
|
||||
supported=0
|
||||
;;
|
||||
esac
|
||||
if [ $supported -eq 0 ]; then
|
||||
echo "Invalid arch: ${UNAME} not supported, please use x86_64/amd64"
|
||||
exit 1;
|
||||
fi
|
||||
}
|
||||
|
||||
check_deps() {
|
||||
check_version "$(env go version 2>/dev/null | sed 's/^.* go\([0-9.]*\).*$/\1/')" "${GO_VERSION}"
|
||||
if [ $? -ge 2 ]; then
|
||||
MISSING="${MISSING} golang(${GO_VERSION})"
|
||||
fi
|
||||
|
||||
check_version "$(env git --version 2>/dev/null | sed -e 's/^.* \([0-9.\].*\).*$/\1/' -e 's/^\([0-9.\]*\).*/\1/g')" "${GIT_VERSION}"
|
||||
if [ $? -ge 2 ]; then
|
||||
MISSING="${MISSING} git"
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
## Check for supported arch
|
||||
assert_is_supported_arch
|
||||
echo -n "Check for supported arch.. "
|
||||
is_supported_arch
|
||||
|
||||
## Check for supported os
|
||||
assert_is_supported_os
|
||||
echo -n "Check for supported os.. "
|
||||
is_supported_os
|
||||
|
||||
## Check for Go environment
|
||||
assert_check_golang_env
|
||||
echo -n "Checking if proper environment variables are set.. "
|
||||
check_golang_env
|
||||
|
||||
## Check for dependencies
|
||||
assert_check_deps
|
||||
echo "Done"
|
||||
echo "Using GOPATH=${GOPATH} and GOROOT=${GOROOT}"
|
||||
|
||||
echo -n "Checking dependencies for Minio.. "
|
||||
check_deps
|
||||
|
||||
## If dependencies are missing, warn the user and abort
|
||||
if [ "x${MISSING}" != "x" ]; then
|
||||
echo "ERROR"
|
||||
echo
|
||||
echo "The following build tools are missing:"
|
||||
echo
|
||||
echo "** ${MISSING} **"
|
||||
echo
|
||||
echo "Please install them "
|
||||
echo "${MISSING}"
|
||||
echo
|
||||
echo "Follow https://docs.minio.io/docs/how-to-install-golang for further instructions"
|
||||
exit 1
|
||||
fi
|
||||
echo "Done"
|
||||
}
|
||||
|
||||
_init && main "$@"
|
||||
|
||||
@@ -15,21 +15,26 @@
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
main() {
|
||||
IFS=':' read -r -a paths <<< "$GOPATH"
|
||||
for path in "${paths[@]}"; do
|
||||
minio_path="$path/src/github.com/minio/minio"
|
||||
if [ -d "$minio_path" ]; then
|
||||
if [ "$minio_path" -ef "$PWD" ]; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
_init() {
|
||||
|
||||
echo "ERROR"
|
||||
echo "Project not found in ${GOPATH}."
|
||||
echo "Follow instructions at https://github.com/minio/minio/blob/master/CONTRIBUTING.md#setup-your-minio-github-repository"
|
||||
exit 1
|
||||
shopt -s extglob
|
||||
|
||||
PWD=$(pwd -P)
|
||||
GOPATH=$(cd "$(go env GOPATH)" ; env pwd -P)
|
||||
}
|
||||
|
||||
main
|
||||
main() {
|
||||
echo "Checking if project is at ${GOPATH}"
|
||||
for minio in $(echo ${GOPATH} | tr ':' ' '); do
|
||||
if [ ! -d ${minio}/src/github.com/minio/minio ]; then
|
||||
echo "Project not found in ${minio}, please follow instructions provided at https://github.com/minio/minio/blob/master/CONTRIBUTING.md#setup-your-minio-github-repository" \
|
||||
&& exit 1
|
||||
fi
|
||||
if [ "x${minio}/src/github.com/minio/minio" != "x${PWD}" ]; then
|
||||
echo "Build outside of ${minio}, two source checkouts found. Exiting." && exit 1
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
_init && main
|
||||
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Minio Cloud Storage, (C) 2017 Minio, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# If command starts with an option, prepend minio.
|
||||
if [ "${1}" != "minio" ]; then
|
||||
if [ -n "${1}" ]; then
|
||||
set -- minio "$@"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Wait for all the hosts to come online and have
|
||||
# their DNS entries populated properly.
|
||||
docker_wait_hosts() {
|
||||
hosts="$@"
|
||||
num_hosts=0
|
||||
# Count number of hosts in arguments.
|
||||
for host in $hosts; do
|
||||
[ $(echo "$host" | grep -E "^http") ] || continue
|
||||
num_hosts=$((num_hosts+1))
|
||||
done
|
||||
if [ $num_hosts -gt 0 ]; then
|
||||
echo -n "Waiting for all hosts to resolve..."
|
||||
while true; do
|
||||
x=0
|
||||
for host in $hosts; do
|
||||
[ $(echo "$host" | grep -E "^http") ] || continue
|
||||
# Extract the domain.
|
||||
host=$(echo $host | sed -e 's/^http[s]\?:\/\/\([^\/]\+\).*/\1/')
|
||||
echo -n .
|
||||
val=$(ping -c 1 $host 2>/dev/null)
|
||||
if [ $? != 0 ]; then
|
||||
echo "Failed to lookup $host"
|
||||
continue
|
||||
fi
|
||||
x=$((x+1))
|
||||
done
|
||||
# Provided hosts same as successful hosts, should break out.
|
||||
test $x -eq $num_hosts && break
|
||||
echo "Failed to resolve hosts.. retrying after 1 second."
|
||||
sleep 1
|
||||
done
|
||||
echo "All hosts are resolving proceeding to initialize Minio."
|
||||
fi
|
||||
}
|
||||
|
||||
## Look for docker secrets in default documented location.
|
||||
docker_secrets_env() {
|
||||
local MINIO_ACCESS_KEY_FILE="/run/secrets/access_key"
|
||||
local MINIO_SECRET_KEY_FILE="/run/secrets/secret_key"
|
||||
|
||||
if [ -f $MINIO_ACCESS_KEY_FILE -a -f $MINIO_SECRET_KEY_FILE ]; then
|
||||
if [ -f $MINIO_ACCESS_KEY_FILE ]; then
|
||||
export MINIO_ACCESS_KEY="$(cat "$MINIO_ACCESS_KEY_FILE")"
|
||||
fi
|
||||
if [ -f $MINIO_SECRET_KEY_FILE ]; then
|
||||
export MINIO_SECRET_KEY="$(cat "$MINIO_SECRET_KEY_FILE")"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
## Set access env from secrets if necessary.
|
||||
docker_secrets_env
|
||||
|
||||
## Wait for all the hosts to come online.
|
||||
docker_wait_hosts "$@"
|
||||
|
||||
exec "$@"
|
||||
@@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Minio Cloud Storage, (C) 2016 Minio, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
minio="github.com/minio/minio"
|
||||
version="2016-09-11T17:42:18Z"
|
||||
release="RELEASE.2016-09-11T17-42-18Z"
|
||||
commit="85e2d886bcb005d49f3876d6849a2b5a55e03cd3"
|
||||
|
||||
echo "-X ${minio}/cmd.Version=${version} -X ${minio}/cmd.ReleaseTag=${release} -X ${minio}/cmd.CommitID=${commit}"
|
||||
|
||||
@@ -27,8 +27,8 @@ import (
|
||||
)
|
||||
|
||||
func genLDFlags(version string) string {
|
||||
ldflagsStr := "-s -w"
|
||||
ldflagsStr += " -X github.com/minio/minio/cmd.Version=" + version
|
||||
var ldflagsStr string
|
||||
ldflagsStr = "-X github.com/minio/minio/cmd.Version=" + version
|
||||
ldflagsStr += " -X github.com/minio/minio/cmd.ReleaseTag=" + releaseTag(version)
|
||||
ldflagsStr += " -X github.com/minio/minio/cmd.CommitID=" + commitID()
|
||||
ldflagsStr += " -X github.com/minio/minio/cmd.ShortCommitID=" + commitID()[:12]
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Minio Cloud Storage, (C) 2015, 2016 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// credential container for access and secret keys.
|
||||
type credential struct {
|
||||
AccessKeyID string `json:"accessKey"`
|
||||
SecretAccessKey string `json:"secretKey"`
|
||||
}
|
||||
|
||||
const (
|
||||
minioAccessID = 20
|
||||
minioSecretID = 40
|
||||
)
|
||||
|
||||
// isValidSecretKey - validate secret key.
|
||||
var isValidSecretKey = regexp.MustCompile(`^.{8,40}$`)
|
||||
|
||||
// isValidAccessKey - validate access key.
|
||||
var isValidAccessKey = regexp.MustCompile(`^[a-zA-Z0-9\\-\\.\\_\\~]{5,20}$`)
|
||||
|
||||
// mustGenAccessKeys - must generate access credentials.
|
||||
func mustGenAccessKeys() (creds credential) {
|
||||
creds, err := genAccessKeys()
|
||||
fatalIf(err, "Unable to generate access keys.")
|
||||
return creds
|
||||
}
|
||||
|
||||
// genAccessKeys - generate access credentials.
|
||||
func genAccessKeys() (credential, error) {
|
||||
accessKeyID, err := genAccessKeyID()
|
||||
if err != nil {
|
||||
return credential{}, err
|
||||
}
|
||||
secretAccessKey, err := genSecretAccessKey()
|
||||
if err != nil {
|
||||
return credential{}, err
|
||||
}
|
||||
creds := credential{
|
||||
AccessKeyID: string(accessKeyID),
|
||||
SecretAccessKey: string(secretAccessKey),
|
||||
}
|
||||
return creds, nil
|
||||
}
|
||||
|
||||
// genAccessKeyID - generate random alpha numeric value using only uppercase characters
|
||||
// takes input as size in integer
|
||||
func genAccessKeyID() ([]byte, error) {
|
||||
alpha := make([]byte, minioAccessID)
|
||||
if _, err := rand.Read(alpha); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < minioAccessID; i++ {
|
||||
alpha[i] = alphaNumericTable[alpha[i]%byte(len(alphaNumericTable))]
|
||||
}
|
||||
return alpha, nil
|
||||
}
|
||||
|
||||
// genSecretAccessKey - generate random base64 numeric value from a random seed.
|
||||
func genSecretAccessKey() ([]byte, error) {
|
||||
rb := make([]byte, minioSecretID)
|
||||
if _, err := rand.Read(rb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(base64.StdEncoding.EncodeToString(rb))[:minioSecretID], nil
|
||||
}
|
||||