Compare commits
69 Commits
v2.42.2
...
feat/compo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83492a4dfb | ||
|
|
bf3ba65782 | ||
|
|
f35b7c9d9d | ||
|
|
e9506c3eae | ||
|
|
bb4465548b | ||
|
|
cf8b5ca768 | ||
|
|
f93d760b1b | ||
|
|
1495ee8dd8 | ||
|
|
8a7279e3ee | ||
|
|
fdff7a38f4 | ||
|
|
f26a68587d | ||
|
|
1c62038344 | ||
|
|
6eb7b4b8ec | ||
|
|
f11fc37409 | ||
|
|
d12a3dc8a8 | ||
|
|
0cfab8770a | ||
|
|
3876ae8fe8 | ||
|
|
77644e4425 | ||
|
|
6592782dc0 | ||
|
|
d6dc250ed4 | ||
|
|
9579f14c34 | ||
|
|
c5acbffe3f | ||
|
|
63142042bc | ||
|
|
1ac0305ed0 | ||
|
|
7860013aa9 | ||
|
|
7a5b964611 | ||
|
|
6950c2e4d2 | ||
|
|
291223b3ce | ||
|
|
99aeb766c3 | ||
|
|
93fe31cc55 | ||
|
|
b9a03fabd9 | ||
|
|
d00b3ea8f8 | ||
|
|
c18afcddc4 | ||
|
|
57db25d08a | ||
|
|
b8f64a1c1b | ||
|
|
de35dee1c5 | ||
|
|
dd883985bb | ||
|
|
97b8911ba8 | ||
|
|
a397e7305d | ||
|
|
d0039afbb7 | ||
|
|
878cdfbc52 | ||
|
|
1165f00bd4 | ||
|
|
949ddffef2 | ||
|
|
c4725428e0 | ||
|
|
d29ad356d1 | ||
|
|
692ca5eaf0 | ||
|
|
b9787c78f3 | ||
|
|
dec7a02737 | ||
|
|
0eade717ce | ||
|
|
e6c674b3c6 | ||
|
|
4ff247e134 | ||
|
|
2f0c1f5fa2 | ||
|
|
07692653ff | ||
|
|
82dc57ad43 | ||
|
|
84e8632b98 | ||
|
|
571ce6cb0d | ||
|
|
783503aece | ||
|
|
b482a9bf0d | ||
|
|
36c6cc203e | ||
|
|
8950585141 | ||
|
|
950028abeb | ||
|
|
280fa562a6 | ||
|
|
6b1fa87ad3 | ||
|
|
cacfb2bc08 | ||
|
|
3107ae4147 | ||
|
|
c182114883 | ||
|
|
342b239ac6 | ||
|
|
0f41aac20b | ||
|
|
cd51a59e72 |
6
.github/CODEOWNERS
vendored
@@ -1,5 +1 @@
|
|||||||
# These owners will be the default owners for everything in the repo.
|
* @filebrowser/maintainers
|
||||||
# Unless a later match takes precedence, @o1egl will be requested for
|
|
||||||
# review when someone opens a pull request.
|
|
||||||
|
|
||||||
* @o1egl @hacdias
|
|
||||||
|
|||||||
42
.github/workflows/main.yaml
vendored
@@ -13,23 +13,23 @@ jobs:
|
|||||||
lint-frontend:
|
lint-frontend:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
package_json_file: "frontend/package.json"
|
package_json_file: "frontend/package.json"
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: "22.x"
|
node-version: "24.x"
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
cache-dependency-path: "frontend/pnpm-lock.yaml"
|
cache-dependency-path: "frontend/pnpm-lock.yaml"
|
||||||
- run: make lint-frontend
|
- run: make lint-frontend
|
||||||
lint-backend:
|
lint-backend:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.24'
|
go-version: '1.25'
|
||||||
- run: make lint-backend
|
- run: make lint-backend
|
||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -41,23 +41,23 @@ jobs:
|
|||||||
test-frontend:
|
test-frontend:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
package_json_file: "frontend/package.json"
|
package_json_file: "frontend/package.json"
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: "22.x"
|
node-version: "24.x"
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
cache-dependency-path: "frontend/pnpm-lock.yaml"
|
cache-dependency-path: "frontend/pnpm-lock.yaml"
|
||||||
- run: make test-frontend
|
- run: make test-frontend
|
||||||
test-backend:
|
test-backend:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.24'
|
go-version: '1.25'
|
||||||
- run: make test-backend
|
- run: make test-backend
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -71,33 +71,33 @@ jobs:
|
|||||||
needs: [lint, test]
|
needs: [lint, test]
|
||||||
if: startsWith(github.event.ref, 'refs/tags/v')
|
if: startsWith(github.event.ref, 'refs/tags/v')
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.23'
|
go-version: '1.25'
|
||||||
- uses: pnpm/action-setup@v4
|
- uses: pnpm/action-setup@v4
|
||||||
with:
|
with:
|
||||||
package_json_file: "frontend/package.json"
|
package_json_file: "frontend/package.json"
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: "22.x"
|
node-version: "24.x"
|
||||||
cache: "pnpm"
|
cache: "pnpm"
|
||||||
cache-dependency-path: "frontend/pnpm-lock.yaml"
|
cache-dependency-path: "frontend/pnpm-lock.yaml"
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v1
|
uses: docker/setup-qemu-action@v3
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: Build frontend
|
- name: Build frontend
|
||||||
run: make build-frontend
|
run: make build-frontend
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
- name: Run GoReleaser
|
- name: Run GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@v2
|
uses: goreleaser/goreleaser-action@v6
|
||||||
with:
|
with:
|
||||||
version: latest
|
version: latest
|
||||||
args: release --clean
|
args: release --clean
|
||||||
|
|||||||
2
.github/workflows/pr-lint.yaml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
name: Validate PR title
|
name: Validate PR title
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: amannn/action-semantic-pull-request@v5
|
- uses: amannn/action-semantic-pull-request@v6
|
||||||
id: lint_pr_title
|
id: lint_pr_title
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
4
.github/workflows/site-pr.yml
vendored
@@ -11,10 +11,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Build site
|
- name: Build site
|
||||||
run: make site
|
run: make site
|
||||||
|
|||||||
4
.github/workflows/site-publish.yml
vendored
@@ -15,10 +15,10 @@ jobs:
|
|||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Build site
|
- name: Build site
|
||||||
run: make site
|
run: make site
|
||||||
|
|||||||
5
.gitignore
vendored
@@ -35,10 +35,5 @@ build/
|
|||||||
/frontend/dist/*
|
/frontend/dist/*
|
||||||
!/frontend/dist/.gitkeep
|
!/frontend/dist/.gitkeep
|
||||||
|
|
||||||
# Playwright files
|
|
||||||
/frontend/test-results/
|
|
||||||
/frontend/playwright-report/
|
|
||||||
/frontend/playwright/.cache/
|
|
||||||
|
|
||||||
default.nix
|
default.nix
|
||||||
Dockerfile.dev
|
Dockerfile.dev
|
||||||
|
|||||||
155
CHANGELOG.md
@@ -1,6 +1,159 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
|
||||||
|
|
||||||
|
## [2.45.2](https://github.com/filebrowser/filebrowser/compare/v2.45.1...v2.45.2) (2025-11-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **deps:** update module github.com/shirou/gopsutil/v3 to v4 ([#5536](https://github.com/filebrowser/filebrowser/issues/5536)) ([fdff7a3](https://github.com/filebrowser/filebrowser/commit/fdff7a38f4711f2b58dfdd60bebbb057bd3a478d))
|
||||||
|
* **deps:** update module gopkg.in/yaml.v2 to v3 ([#5537](https://github.com/filebrowser/filebrowser/issues/5537)) ([f26a685](https://github.com/filebrowser/filebrowser/commit/f26a68587d8432b536453093f42dc255d19d10fa))
|
||||||
|
|
||||||
|
### [2.45.1](https://github.com/filebrowser/filebrowser/compare/v2.45.0...v2.45.1) (2025-11-11)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* share page preview items to contain baseUrl ([#5510](https://github.com/filebrowser/filebrowser/issues/5510)) ([6950c2e](https://github.com/filebrowser/filebrowser/commit/6950c2e4d2868f06235f93c0a18b303b4095ca0a))
|
||||||
|
|
||||||
|
## [2.45.0](https://github.com/filebrowser/filebrowser/compare/v2.44.2...v2.45.0) (2025-11-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* update translations ([#5458](https://github.com/filebrowser/filebrowser/issues/5458)) ([b9a03fa](https://github.com/filebrowser/filebrowser/commit/b9a03fabd98119d6588882f5ba2a7d29b012d729))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* support croatian ([#5502](https://github.com/filebrowser/filebrowser/issues/5502)) ([93fe31c](https://github.com/filebrowser/filebrowser/commit/93fe31cc55c9d9d27c634993619a768fa700da1d))
|
||||||
|
|
||||||
|
### [2.44.2](https://github.com/filebrowser/filebrowser/compare/v2.44.1...v2.44.2) (2025-10-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **http:** remove auth query parameter ([57db25d](https://github.com/filebrowser/filebrowser/commit/57db25d08a1ef2cd0b41f34e312b7b7c35c7ed38))
|
||||||
|
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
* **deps-dev:** bump vite from 6.3.6 to 6.4.1 in /frontend ([b8f64a1](https://github.com/filebrowser/filebrowser/commit/b8f64a1c1bc235df784d7f52abd3a9e84c6db6ce))
|
||||||
|
|
||||||
|
### [2.44.1](https://github.com/filebrowser/filebrowser/compare/v2.44.0...v2.44.1) (2025-10-17)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **auth:** prevent integer overflow in logout timer using safeTimeout ([#5470](https://github.com/filebrowser/filebrowser/issues/5470)) ([dd88398](https://github.com/filebrowser/filebrowser/commit/dd883985bb484af9dfea2677a40d56999fdc72f3))
|
||||||
|
* editor discard prompt doesn't save nor discard ([a397e73](https://github.com/filebrowser/filebrowser/commit/a397e7305d1572baf67823413f97a29eea38f0cc))
|
||||||
|
* wrong url on settings branding link ([d0039af](https://github.com/filebrowser/filebrowser/commit/d0039afbb76a9364c1e6ac9715ccc3c239dc8cb6))
|
||||||
|
|
||||||
|
|
||||||
|
### Refactorings
|
||||||
|
|
||||||
|
* use slices.Contains to simplify code ([#5483](https://github.com/filebrowser/filebrowser/issues/5483)) ([97b8911](https://github.com/filebrowser/filebrowser/commit/97b8911ba8a65456091cbec0202f6b5209fcf363))
|
||||||
|
|
||||||
|
## [2.44.0](https://github.com/filebrowser/filebrowser/compare/v2.43.0...v2.44.0) (2025-09-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* allow setting ace editor theme ([#3826](https://github.com/filebrowser/filebrowser/issues/3826)) ([b9787c7](https://github.com/filebrowser/filebrowser/commit/b9787c78f3889171f94db19e7655dce68c64b6fb))
|
||||||
|
* Improved path display in the new file and directory modal ([#5451](https://github.com/filebrowser/filebrowser/issues/5451)) ([d29ad35](https://github.com/filebrowser/filebrowser/commit/d29ad356d1067c87b2821debab91286549f512a0))
|
||||||
|
* Translate frontend/src/i18n/en.json in no ([dec7a02](https://github.com/filebrowser/filebrowser/commit/dec7a027378fbc6948d203199c44a640a141bcad))
|
||||||
|
* Updates for project File Browser ([#5446](https://github.com/filebrowser/filebrowser/issues/5446)) ([4ff247e](https://github.com/filebrowser/filebrowser/commit/4ff247e134e4d61668ee656a258ed67f71414e18))
|
||||||
|
* Updates for project File Browser ([#5450](https://github.com/filebrowser/filebrowser/issues/5450)) ([0eade71](https://github.com/filebrowser/filebrowser/commit/0eade717ce9d04bf48051922f11d983edbc7c2d0))
|
||||||
|
* Updates for project File Browser ([#5457](https://github.com/filebrowser/filebrowser/issues/5457)) ([1165f00](https://github.com/filebrowser/filebrowser/commit/1165f00bd4dcb0dcfbc084f54f51902ba4b4a714))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* computation of file path ([c472542](https://github.com/filebrowser/filebrowser/commit/c4725428e07da72b855009e2c13c6ed91d32e0b7))
|
||||||
|
* show login when session token expires ([e6c674b](https://github.com/filebrowser/filebrowser/commit/e6c674b3c616831942c4d4aacab0907d58003e23))
|
||||||
|
* some formatting issues with i18n files ([949ddff](https://github.com/filebrowser/filebrowser/commit/949ddffef20e38169902c5fd74dca4815dcecf11))
|
||||||
|
* **upload:** throttle upload speed calculation to 100ms to avoid Infinity MB/s ([#5456](https://github.com/filebrowser/filebrowser/issues/5456)) ([692ca5e](https://github.com/filebrowser/filebrowser/commit/692ca5eaf01e4dcf346ba03f82c5dbd50cce246b))
|
||||||
|
|
||||||
|
## [2.43.0](https://github.com/filebrowser/filebrowser/compare/v2.42.5...v2.43.0) (2025-09-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* "save changes" button to discard changes dialog ([84e8632](https://github.com/filebrowser/filebrowser/commit/84e8632b98e315bfef2da77dd7d1049daec99241))
|
||||||
|
* Translate frontend/src/i18n/en.json in es ([571ce6c](https://github.com/filebrowser/filebrowser/commit/571ce6cb0d7c8725d1cc1a3238ea506ddc72b060))
|
||||||
|
* Translate frontend/src/i18n/en.json in fr ([6b1fa87](https://github.com/filebrowser/filebrowser/commit/6b1fa87ad38ebbb1a9c5d0e5fc88ba796c148bcf))
|
||||||
|
* Updates for project File Browser ([#5427](https://github.com/filebrowser/filebrowser/issues/5427)) ([8950585](https://github.com/filebrowser/filebrowser/commit/89505851414bfcee6b9ff02087eb4cec51c330f6))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* optimize markdown preview height ([783503a](https://github.com/filebrowser/filebrowser/commit/783503aece7fca9e26f7e849b0e7478aba976acb))
|
||||||
|
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* build(deps): bump github.com/ulikunitz/xz from 0.5.12 to 0.5.14 ([0769265](https://github.com/filebrowser/filebrowser/commit/07692653ffe0ea5e517e6dc1fd3961172e931843))
|
||||||
|
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
* **deps-dev:** bump vite from 6.1.6 to 6.3.6 in /frontend ([36c6cc2](https://github.com/filebrowser/filebrowser/commit/36c6cc203e10947439519a0413d5817921a1690d))
|
||||||
|
* **deps:** bump github.com/go-viper/mapstructure/v2 in /tools ([280fa56](https://github.com/filebrowser/filebrowser/commit/280fa562a67824887ae6e2530a3b73739d6e1bb4))
|
||||||
|
* **deps:** bump github.com/ulikunitz/xz from 0.5.12 to 0.5.14 ([950028a](https://github.com/filebrowser/filebrowser/commit/950028abebe2898bac4ecfd8715c0967246310cb))
|
||||||
|
|
||||||
|
|
||||||
|
### Refactorings
|
||||||
|
|
||||||
|
* to use strings.Lines ([b482a9b](https://github.com/filebrowser/filebrowser/commit/b482a9bf0d292ec6542d2145a4408971e4c985f1))
|
||||||
|
|
||||||
|
## [2.43.0](https://github.com/filebrowser/filebrowser/compare/v2.42.5...v2.43.0) (2025-09-13)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* "save changes" button to discard changes dialog ([84e8632](https://github.com/filebrowser/filebrowser/commit/84e8632b98e315bfef2da77dd7d1049daec99241))
|
||||||
|
* Translate frontend/src/i18n/en.json in es ([571ce6c](https://github.com/filebrowser/filebrowser/commit/571ce6cb0d7c8725d1cc1a3238ea506ddc72b060))
|
||||||
|
* Translate frontend/src/i18n/en.json in fr ([6b1fa87](https://github.com/filebrowser/filebrowser/commit/6b1fa87ad38ebbb1a9c5d0e5fc88ba796c148bcf))
|
||||||
|
* Updates for project File Browser ([#5427](https://github.com/filebrowser/filebrowser/issues/5427)) ([8950585](https://github.com/filebrowser/filebrowser/commit/89505851414bfcee6b9ff02087eb4cec51c330f6))
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* optimize markdown preview height ([783503a](https://github.com/filebrowser/filebrowser/commit/783503aece7fca9e26f7e849b0e7478aba976acb))
|
||||||
|
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
* **deps-dev:** bump vite from 6.1.6 to 6.3.6 in /frontend ([36c6cc2](https://github.com/filebrowser/filebrowser/commit/36c6cc203e10947439519a0413d5817921a1690d))
|
||||||
|
* **deps:** bump github.com/go-viper/mapstructure/v2 in /tools ([280fa56](https://github.com/filebrowser/filebrowser/commit/280fa562a67824887ae6e2530a3b73739d6e1bb4))
|
||||||
|
* **deps:** bump github.com/ulikunitz/xz from 0.5.12 to 0.5.14 ([950028a](https://github.com/filebrowser/filebrowser/commit/950028abebe2898bac4ecfd8715c0967246310cb))
|
||||||
|
|
||||||
|
|
||||||
|
### Refactorings
|
||||||
|
|
||||||
|
* to use strings.Lines ([b482a9b](https://github.com/filebrowser/filebrowser/commit/b482a9bf0d292ec6542d2145a4408971e4c985f1))
|
||||||
|
|
||||||
|
### [2.42.5](https://github.com/filebrowser/filebrowser/compare/v2.42.4...v2.42.5) (2025-08-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* "new folder" button not working in the move and copy popup ([#5368](https://github.com/filebrowser/filebrowser/issues/5368)) ([3107ae4](https://github.com/filebrowser/filebrowser/commit/3107ae41475ae9383c3af414d25a133e549f8087))
|
||||||
|
|
||||||
|
### [2.42.4](https://github.com/filebrowser/filebrowser/compare/v2.42.3...v2.42.4) (2025-08-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add libcap to Dockerfile.s6 ([342b239](https://github.com/filebrowser/filebrowser/commit/342b239ac6f4af2453d5f7aa27f7f0093024dd72))
|
||||||
|
|
||||||
|
### [2.42.3](https://github.com/filebrowser/filebrowser/compare/v2.42.2...v2.42.3) (2025-08-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add missing CLI flags for user management ([#5351](https://github.com/filebrowser/filebrowser/issues/5351)) ([cd51a59](https://github.com/filebrowser/filebrowser/commit/cd51a59e72c72560fce7bcc9b12aaf02646b699c))
|
||||||
|
|
||||||
### [2.42.2](https://github.com/filebrowser/filebrowser/compare/v2.42.1...v2.42.2) (2025-08-06)
|
### [2.42.2](https://github.com/filebrowser/filebrowser/compare/v2.42.1...v2.42.2) (2025-08-06)
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
FROM ghcr.io/linuxserver/baseimage-alpine:3.22
|
FROM ghcr.io/linuxserver/baseimage-alpine:3.22
|
||||||
|
|
||||||
RUN apk update && \
|
RUN apk update && \
|
||||||
apk --no-cache add ca-certificates mailcap jq
|
apk --no-cache add ca-certificates mailcap jq libcap
|
||||||
|
|
||||||
# Make user and create necessary directories
|
# Make user and create necessary directories
|
||||||
RUN mkdir -p /config /database /srv && \
|
RUN mkdir -p /config /database /srv && \
|
||||||
@@ -12,7 +12,8 @@ COPY filebrowser /bin/filebrowser
|
|||||||
COPY docker/common/ /
|
COPY docker/common/ /
|
||||||
COPY docker/s6/ /
|
COPY docker/s6/ /
|
||||||
|
|
||||||
RUN chown -R abc:abc /bin/filebrowser /defaults healthcheck.sh
|
RUN chown -R abc:abc /bin/filebrowser /defaults healthcheck.sh && \
|
||||||
|
setcap 'cap_net_bind_service=+ep' /bin/filebrowser
|
||||||
|
|
||||||
# Define healthcheck script
|
# Define healthcheck script
|
||||||
HEALTHCHECK --start-period=2s --interval=5s --timeout=3s CMD /healthcheck.sh
|
HEALTHCHECK --start-period=2s --interval=5s --timeout=3s CMD /healthcheck.sh
|
||||||
|
|||||||
14
Makefile
@@ -46,10 +46,6 @@ lint-frontend: ## Run frontend linters
|
|||||||
lint-backend: | $(golangci-lint) ## Run backend linters
|
lint-backend: | $(golangci-lint) ## Run backend linters
|
||||||
$Q $(golangci-lint) run -v
|
$Q $(golangci-lint) run -v
|
||||||
|
|
||||||
.PHONY: lint-commits
|
|
||||||
lint-commits: $(commitlint) ## Run commit linters
|
|
||||||
$Q ./scripts/commitlint.sh
|
|
||||||
|
|
||||||
fmt: $(goimports) ## Format source files
|
fmt: $(goimports) ## Format source files
|
||||||
$Q $(goimports) -local $(MODULE) -w $$(find . -type f -name '*.go' -not -path "./vendor/*")
|
$Q $(goimports) -local $(MODULE) -w $$(find . -type f -name '*.go' -not -path "./vendor/*")
|
||||||
|
|
||||||
@@ -57,9 +53,13 @@ clean: clean-tools ## Clean
|
|||||||
|
|
||||||
## Release:
|
## Release:
|
||||||
|
|
||||||
.PHONY: bump-version
|
.PHONY: release-dry-run
|
||||||
bump-version: $(standard-version) ## Bump app version
|
release-dry-run:
|
||||||
$Q ./scripts/bump_version.sh
|
pnpm dlx commit-and-tag-version --dry-run --skip
|
||||||
|
|
||||||
|
.PHONY: release
|
||||||
|
release:
|
||||||
|
pnpm dlx commit-and-tag-version -s
|
||||||
|
|
||||||
.PHONY: site
|
.PHONY: site
|
||||||
site: ## Build site
|
site: ## Build site
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://raw.githubusercontent.com/filebrowser/logo/master/banner.png" width="550"/>
|
<img src="https://raw.githubusercontent.com/filebrowser/filebrowser/master/branding/banner.png" width="550"/>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
[](https://github.com/filebrowser/filebrowser/actions/workflows/main.yaml)
|
[](https://github.com/filebrowser/filebrowser/actions/workflows/main.yaml)
|
||||||
[](https://goreportcard.com/report/github.com/filebrowser/filebrowser)
|
[](https://goreportcard.com/report/github.com/filebrowser/filebrowser/v2)
|
||||||
[](http://godoc.org/github.com/filebrowser/filebrowser)
|
|
||||||
[](https://github.com/filebrowser/filebrowser/releases/latest)
|
[](https://github.com/filebrowser/filebrowser/releases/latest)
|
||||||
[](http://webchat.freenode.net/?channels=%23filebrowser)
|
|
||||||
|
|
||||||
File Browser provides a file managing interface within a specified directory and it can be used to upload, delete, preview and edit your files. It is a **create-your-own-cloud**-kind of software where you can just install it on your server, direct it to a path and access your files through a nice web interface.
|
File Browser provides a file managing interface within a specified directory and it can be used to upload, delete, preview and edit your files. It is a **create-your-own-cloud**-kind of software where you can just install it on your server, direct it to a path and access your files through a nice web interface.
|
||||||
|
|
||||||
|
|||||||
11
auth/hook.go
@@ -8,6 +8,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
fbErrors "github.com/filebrowser/filebrowser/v2/errors"
|
fbErrors "github.com/filebrowser/filebrowser/v2/errors"
|
||||||
@@ -123,7 +124,7 @@ func (a *HookAuth) GetValues(s string) {
|
|||||||
s = strings.ReplaceAll(s, "\r\n", "\n")
|
s = strings.ReplaceAll(s, "\r\n", "\n")
|
||||||
|
|
||||||
// iterate input lines
|
// iterate input lines
|
||||||
for _, val := range strings.Split(s, "\n") {
|
for val := range strings.Lines(s) {
|
||||||
v := strings.SplitN(val, "=", 2)
|
v := strings.SplitN(val, "=", 2)
|
||||||
|
|
||||||
// skips non key and value format
|
// skips non key and value format
|
||||||
@@ -266,13 +267,7 @@ var validHookFields = []string{
|
|||||||
|
|
||||||
// IsValid checks if the provided field is on the valid fields list
|
// IsValid checks if the provided field is on the valid fields list
|
||||||
func (hf *hookFields) IsValid(field string) bool {
|
func (hf *hookFields) IsValid(field string) bool {
|
||||||
for _, val := range validHookFields {
|
return slices.Contains(validHookFields, field)
|
||||||
if field == val {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetString returns the string value or provided default
|
// GetString returns the string value or provided default
|
||||||
|
|||||||
BIN
branding/banner.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
1
branding/banner.svg
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
branding/icon.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
1
branding/icon.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="700" height="700" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd"><defs><style>.prefix__fil1{fill:#fefefe}.prefix__fil6{fill:#006498}.prefix__fil5{fill:#bdeaff}</style></defs><g id="prefix__Layer_x0020_1"><path d="M80 0h540c44 0 80 36 80 80v540c0 44-36 80-80 80H80c-44 0-80-36-80-80V80C0 36 36 0 80 0z" fill="#455a64"/><path class="prefix__fil1" d="M350 71c154 0 279 125 279 279S504 629 350 629 71 504 71 350 196 71 350 71z"/><path d="M475 236l118 151c3 116-149 252-292 198l-76-99 114-156s138-95 136-94z" fill="#332c2b" fill-opacity=".149"/><path d="M231 211h208l38 24v246c0 5-3 8-8 8H231c-5 0-8-3-8-8V219c0-5 3-8 8-8z" fill="#2bbcff"/><path d="M231 211h208l38 24v2l-37-23H231c-4 0-7 3-7 7v263c-1-1-1-2-1-3V219c0-5 3-8 8-8z" fill="#53c6fc"/><path class="prefix__fil5" d="M305 212h113v98H305zM255 363h189c3 0 5 2 5 4v116H250V367c0-2 2-4 5-4z"/><path class="prefix__fil6" d="M250 470h199v13H250zM380 226h10c3 0 6 2 6 5v40c0 3-3 6-6 6h-10c-3 0-6-3-6-6v-40c0-3 3-5 6-5z"/><path class="prefix__fil1" d="M254 226c10 0 17 7 17 17 0 9-7 16-17 16-9 0-17-7-17-16 0-10 8-17 17-17z"/><path class="prefix__fil6" d="M267 448h165c2 0 3 1 3 3 0 1-1 3-3 3H267c-2 0-3-2-3-3 0-2 1-3 3-3zM267 415h165c2 0 3 1 3 3 0 1-1 2-3 2H267c-2 0-3-1-3-2 0-2 1-3 3-3zM267 381h165c2 0 3 2 3 3 0 2-1 3-3 3H267c-2 0-3-1-3-3 0-1 1-3 3-3z"/><path class="prefix__fil1" d="M236 472c3 0 5 2 5 5 0 2-2 4-5 4s-5-2-5-4c0-3 2-5 5-5zM463 472c3 0 5 2 5 5 0 2-2 4-5 4s-5-2-5-4c0-3 2-5 5-5z"/><path class="prefix__fil6" d="M305 212h-21v98h21z"/><path d="M477 479v2c0 5-3 8-8 8H231c-5 0-8-3-8-8v-2c0 4 3 8 8 8h238c5 0 8-4 8-8z" fill="#0ea5eb"/><path d="M350 70c155 0 280 125 280 280S505 630 350 630 70 505 70 350 195 70 350 70zm0 46c129 0 234 105 234 234S479 584 350 584 116 479 116 350s105-234 234-234z" fill="#2979ff"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
BIN
branding/logo.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
1
branding/logo.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="560" height="560" version="1.1" id="prefix__svg44" clip-rule="evenodd" fill-rule="evenodd" image-rendering="optimizeQuality" shape-rendering="geometricPrecision" text-rendering="geometricPrecision"><defs id="prefix__defs4"><style type="text/css" id="style2">.prefix__fil1{fill:#fefefe}.prefix__fil6{fill:#006498}.prefix__fil5{fill:#bdeaff}</style></defs><g id="prefix__g85" transform="translate(-70 -70)"><path class="prefix__fil1" d="M350 71c154 0 279 125 279 279S504 629 350 629 71 504 71 350 196 71 350 71z" id="prefix__path9" fill="#fefefe"/><path d="M475 236l118 151c3 116-149 252-292 198l-76-99 114-156s138-95 136-94z" id="prefix__path11" fill="#332c2b" fill-opacity=".149"/><path d="M231 211h208l38 24v246c0 5-3 8-8 8H231c-5 0-8-3-8-8V219c0-5 3-8 8-8z" id="prefix__path13" fill="#2bbcff"/><path d="M231 211h208l38 24v2l-37-23H231c-4 0-7 3-7 7v263c-1-1-1-2-1-3V219c0-5 3-8 8-8z" id="prefix__path15" fill="#53c6fc"/><path class="prefix__fil5" id="prefix__polygon17" fill="#bdeaff" d="M305 212h113v98H305z"/><path class="prefix__fil5" d="M255 363h189c3 0 5 2 5 4v116H250V367c0-2 2-4 5-4z" id="prefix__path19" fill="#bdeaff"/><path class="prefix__fil6" id="prefix__polygon21" fill="#006498" d="M250 470h199v13H250z"/><path class="prefix__fil6" d="M380 226h10c3 0 6 2 6 5v40c0 3-3 6-6 6h-10c-3 0-6-3-6-6v-40c0-3 3-5 6-5z" id="prefix__path23" fill="#006498"/><path class="prefix__fil1" d="M254 226c10 0 17 7 17 17 0 9-7 16-17 16-9 0-17-7-17-16 0-10 8-17 17-17z" id="prefix__path25" fill="#fefefe"/><path class="prefix__fil6" d="M267 448h165c2 0 3 1 3 3 0 1-1 3-3 3H267c-2 0-3-2-3-3 0-2 1-3 3-3z" id="prefix__path27" fill="#006498"/><path class="prefix__fil6" d="M267 415h165c2 0 3 1 3 3 0 1-1 2-3 2H267c-2 0-3-1-3-2 0-2 1-3 3-3z" id="prefix__path29" fill="#006498"/><path class="prefix__fil6" d="M267 381h165c2 0 3 2 3 3 0 2-1 3-3 3H267c-2 0-3-1-3-3 0-1 1-3 3-3z" id="prefix__path31" fill="#006498"/><path class="prefix__fil1" d="M236 472c3 0 5 2 5 5 0 2-2 4-5 4s-5-2-5-4c0-3 2-5 5-5z" id="prefix__path33" fill="#fefefe"/><path class="prefix__fil1" d="M463 472c3 0 5 2 5 5 0 2-2 4-5 4s-5-2-5-4c0-3 2-5 5-5z" id="prefix__path35" fill="#fefefe"/><path class="prefix__fil6" id="prefix__polygon37" fill="#006498" d="M305 212h-21v98h21z"/><path d="M477 479v2c0 5-3 8-8 8H231c-5 0-8-3-8-8v-2c0 4 3 8 8 8h238c5 0 8-4 8-8z" id="prefix__path39" fill="#0ea5eb"/><path d="M350 70c155 0 280 125 280 280S505 630 350 630 70 505 70 350 195 70 350 70zm0 46c129 0 234 105 234 234S479 584 350 584 116 479 116 350s105-234 234-234z" id="prefix__path41" fill="#2979ff"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -221,6 +221,7 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut
|
|||||||
fmt.Fprintf(w, "\tFile Creation Mode:\t%O\n", set.FileMode)
|
fmt.Fprintf(w, "\tFile Creation Mode:\t%O\n", set.FileMode)
|
||||||
fmt.Fprintf(w, "\tDirectory Creation Mode:\t%O\n", set.DirMode)
|
fmt.Fprintf(w, "\tDirectory Creation Mode:\t%O\n", set.DirMode)
|
||||||
fmt.Fprintf(w, "\tCommands:\t%s\n", strings.Join(set.Defaults.Commands, " "))
|
fmt.Fprintf(w, "\tCommands:\t%s\n", strings.Join(set.Defaults.Commands, " "))
|
||||||
|
fmt.Fprintf(w, "\tAce editor syntax highlighting theme:\t%s\n", set.Defaults.AceEditorTheme)
|
||||||
fmt.Fprintf(w, "\tSorting:\n")
|
fmt.Fprintf(w, "\tSorting:\n")
|
||||||
fmt.Fprintf(w, "\t\tBy:\t%s\n", set.Defaults.Sorting.By)
|
fmt.Fprintf(w, "\t\tBy:\t%s\n", set.Defaults.Sorting.By)
|
||||||
fmt.Fprintf(w, "\t\tAsc:\t%t\n", set.Defaults.Sorting.Asc)
|
fmt.Fprintf(w, "\t\tAsc:\t%t\n", set.Defaults.Sorting.Asc)
|
||||||
|
|||||||
@@ -427,6 +427,7 @@ func quickSetup(flags *pflag.FlagSet, d pythonData) error {
|
|||||||
Scope: ".",
|
Scope: ".",
|
||||||
Locale: "en",
|
Locale: "en",
|
||||||
SingleClick: false,
|
SingleClick: false,
|
||||||
|
AceEditorTheme: getStringParam(flags, "defaults.aceEditorTheme"),
|
||||||
Perm: users.Permissions{
|
Perm: users.Permissions{
|
||||||
Admin: false,
|
Admin: false,
|
||||||
Execute: true,
|
Execute: true,
|
||||||
|
|||||||
@@ -77,6 +77,9 @@ func addUserFlags(flags *pflag.FlagSet) {
|
|||||||
flags.String("locale", "en", "locale for users")
|
flags.String("locale", "en", "locale for users")
|
||||||
flags.String("viewMode", string(users.ListViewMode), "view mode for users")
|
flags.String("viewMode", string(users.ListViewMode), "view mode for users")
|
||||||
flags.Bool("singleClick", false, "use single clicks only")
|
flags.Bool("singleClick", false, "use single clicks only")
|
||||||
|
flags.Bool("dateFormat", false, "use date format (true for absolute time, false for relative)")
|
||||||
|
flags.Bool("hideDotfiles", false, "hide dotfiles")
|
||||||
|
flags.String("aceEditorTheme", "", "ace editor's syntax highlighting theme for users")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getViewMode(flags *pflag.FlagSet) (users.ViewMode, error) {
|
func getViewMode(flags *pflag.FlagSet) (users.ViewMode, error) {
|
||||||
@@ -108,6 +111,8 @@ func getUserDefaults(flags *pflag.FlagSet, defaults *settings.UserDefaults, all
|
|||||||
defaults.ViewMode, err = getViewMode(flags)
|
defaults.ViewMode, err = getViewMode(flags)
|
||||||
case "singleClick":
|
case "singleClick":
|
||||||
defaults.SingleClick, err = getBool(flags, flag.Name)
|
defaults.SingleClick, err = getBool(flags, flag.Name)
|
||||||
|
case "aceEditorTheme":
|
||||||
|
defaults.AceEditorTheme, err = getString(flags, flag.Name)
|
||||||
case "perm.admin":
|
case "perm.admin":
|
||||||
defaults.Perm.Admin, err = getBool(flags, flag.Name)
|
defaults.Perm.Admin, err = getBool(flags, flag.Name)
|
||||||
case "perm.execute":
|
case "perm.execute":
|
||||||
|
|||||||
@@ -36,10 +36,22 @@ var usersAddCmd = &cobra.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dateFormat, err := getBool(cmd.Flags(), "dateFormat")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
hideDotfiles, err := getBool(cmd.Flags(), "hideDotfiles")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
user := &users.User{
|
user := &users.User{
|
||||||
Username: args[0],
|
Username: args[0],
|
||||||
Password: password,
|
Password: password,
|
||||||
LockPassword: lockPassword,
|
LockPassword: lockPassword,
|
||||||
|
DateFormat: dateFormat,
|
||||||
|
HideDotfiles: hideDotfiles,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Defaults.Apply(user)
|
s.Defaults.Apply(user)
|
||||||
|
|||||||
@@ -76,6 +76,14 @@ options you want to change.`,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
user.DateFormat, err = getBool(flags, "dateFormat")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
user.HideDotfiles, err = getBool(flags, "hideDotfiles")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if newUsername != "" {
|
if newUsername != "" {
|
||||||
user.Username = newUsername
|
user.Username = newUsername
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
"github.com/asdine/storm/v3"
|
"github.com/asdine/storm/v3"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v3"
|
||||||
|
|
||||||
"github.com/filebrowser/filebrowser/v2/settings"
|
"github.com/filebrowser/filebrowser/v2/settings"
|
||||||
"github.com/filebrowser/filebrowser/v2/storage"
|
"github.com/filebrowser/filebrowser/v2/storage"
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
//go:build !dev
|
//go:build !dev
|
||||||
// +build !dev
|
|
||||||
|
|
||||||
package frontend
|
package frontend
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
//go:build dev
|
//go:build dev
|
||||||
// +build dev
|
|
||||||
|
|
||||||
package frontend
|
package frontend
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,11 @@
|
|||||||
|
|
||||||
<link rel="icon" type="image/svg+xml" href="/img/icons/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/img/icons/favicon.svg" />
|
||||||
<link rel="shortcut icon" href="/img/icons/favicon.ico" />
|
<link rel="shortcut icon" href="/img/icons/favicon.ico" />
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/img/icons/apple-touch-icon.png" />
|
<link
|
||||||
|
rel="apple-touch-icon"
|
||||||
|
sizes="180x180"
|
||||||
|
href="/img/icons/apple-touch-icon.png"
|
||||||
|
/>
|
||||||
<meta name="apple-mobile-web-app-title" content="File Browser" />
|
<meta name="apple-mobile-web-app-title" content="File Browser" />
|
||||||
|
|
||||||
<!-- Add to home screen for Android and modern mobile browsers -->
|
<!-- Add to home screen for Android and modern mobile browsers -->
|
||||||
|
|||||||
@@ -4,37 +4,35 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22.0.0",
|
"node": ">=24.0.0",
|
||||||
"pnpm": ">=9.0.0"
|
"pnpm": ">=10.0.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
"build": "pnpm run typecheck && vite build",
|
"build": "pnpm run typecheck && vite build",
|
||||||
"clean": "find ./dist -maxdepth 1 -mindepth 1 ! -name '.gitkeep' -exec rm -r {} +",
|
"clean": "find ./dist -maxdepth 1 -mindepth 1 ! -name '.gitkeep' -exec rm -r {} +",
|
||||||
"typecheck": "vue-tsc -p ./tsconfig.tsc.json --noEmit",
|
"typecheck": "vue-tsc -p ./tsconfig.app.json --noEmit",
|
||||||
"lint": "eslint src/",
|
"lint": "eslint src/",
|
||||||
"lint:fix": "eslint --fix src/",
|
"lint:fix": "eslint --fix src/",
|
||||||
"format": "prettier --write .",
|
"format": "prettier --write ."
|
||||||
"test": "playwright test"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chenfengyuan/vue-number-input": "^2.0.1",
|
"@chenfengyuan/vue-number-input": "^2.0.1",
|
||||||
"@vueuse/core": "^12.5.0",
|
"@vueuse/core": "^14.0.0",
|
||||||
"@vueuse/integrations": "^12.5.0",
|
"@vueuse/integrations": "^14.0.0",
|
||||||
"ace-builds": "^1.43.2",
|
"ace-builds": "^1.43.2",
|
||||||
"core-js": "^3.44.0",
|
|
||||||
"dayjs": "^1.11.13",
|
"dayjs": "^1.11.13",
|
||||||
"dompurify": "^3.2.6",
|
"dompurify": "^3.2.6",
|
||||||
"epubjs": "^0.3.93",
|
"epubjs": "^0.3.93",
|
||||||
"filesize": "^10.1.1",
|
"filesize": "^11.0.13",
|
||||||
"js-base64": "^3.7.7",
|
"js-base64": "^3.7.7",
|
||||||
"jwt-decode": "^4.0.0",
|
"jwt-decode": "^4.0.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"marked": "^15.0.6",
|
"marked": "^17.0.0",
|
||||||
"material-icons": "^1.13.14",
|
"material-icons": "^1.13.14",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"pinia": "^2.3.1",
|
"pinia": "^3.0.4",
|
||||||
"pretty-bytes": "^6.1.1",
|
"pretty-bytes": "^7.1.0",
|
||||||
"qrcode.vue": "^3.6.0",
|
"qrcode.vue": "^3.6.0",
|
||||||
"tus-js-client": "^4.3.1",
|
"tus-js-client": "^4.3.1",
|
||||||
"utif": "^3.1.0",
|
"utif": "^3.1.0",
|
||||||
@@ -50,30 +48,28 @@
|
|||||||
"vue-toastification": "^2.0.0-rc.5"
|
"vue-toastification": "^2.0.0-rc.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@intlify/unplugin-vue-i18n": "^6.0.8",
|
"@intlify/unplugin-vue-i18n": "^11.0.1",
|
||||||
"@playwright/test": "^1.54.1",
|
"@tsconfig/node24": "^24.0.2",
|
||||||
"@tsconfig/node22": "^22.0.2",
|
|
||||||
"@types/lodash-es": "^4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/node": "^22.10.10",
|
"@types/node": "^24.10.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.37.0",
|
"@typescript-eslint/eslint-plugin": "^8.37.0",
|
||||||
"@vitejs/plugin-legacy": "^6.0.0",
|
"@vitejs/plugin-legacy": "^7.2.1",
|
||||||
"@vitejs/plugin-vue": "^5.0.4",
|
"@vitejs/plugin-vue": "^6.0.1",
|
||||||
"@vue/eslint-config-prettier": "^10.2.0",
|
"@vue/eslint-config-prettier": "^10.2.0",
|
||||||
"@vue/eslint-config-typescript": "^14.6.0",
|
"@vue/eslint-config-typescript": "^14.6.0",
|
||||||
"@vue/tsconfig": "^0.7.0",
|
"@vue/tsconfig": "^0.8.1",
|
||||||
"autoprefixer": "^10.4.21",
|
"autoprefixer": "^10.4.21",
|
||||||
"concurrently": "^9.2.0",
|
|
||||||
"eslint": "^9.31.0",
|
"eslint": "^9.31.0",
|
||||||
"eslint-config-prettier": "^10.1.5",
|
"eslint-config-prettier": "^10.1.5",
|
||||||
"eslint-plugin-prettier": "^5.5.1",
|
"eslint-plugin-prettier": "^5.5.1",
|
||||||
"eslint-plugin-vue": "^9.24.0",
|
"eslint-plugin-vue": "^10.5.1",
|
||||||
"jsdom": "^26.1.0",
|
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"terser": "^5.43.1",
|
"terser": "^5.43.1",
|
||||||
"vite": "^6.1.6",
|
"typescript": "^5.9.3",
|
||||||
"vite-plugin-compression2": "^1.0.0",
|
"vite": "^7.2.2",
|
||||||
"vue-tsc": "^2.2.0"
|
"vite-plugin-compression2": "^2.3.1",
|
||||||
|
"vue-tsc": "^3.1.3"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0"
|
"packageManager": "pnpm@10.22.0+sha512.bf049efe995b28f527fd2b41ae0474ce29186f7edcb3bf545087bd61fbbebb2bf75362d1307fda09c2d288e1e499787ac12d4fcb617a974718a6051f2eee741c"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,80 +0,0 @@
|
|||||||
import { defineConfig, devices } from "@playwright/test";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read environment variables from file.
|
|
||||||
* https://github.com/motdotla/dotenv
|
|
||||||
*/
|
|
||||||
// require('dotenv').config();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* See https://playwright.dev/docs/test-configuration.
|
|
||||||
*/
|
|
||||||
export default defineConfig({
|
|
||||||
testDir: "./tests",
|
|
||||||
/* Run tests in files in parallel */
|
|
||||||
fullyParallel: true,
|
|
||||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
|
||||||
forbidOnly: !!process.env.CI,
|
|
||||||
/* Retry on CI only */
|
|
||||||
retries: process.env.CI ? 2 : 0,
|
|
||||||
/* Opt out of parallel tests on CI. */
|
|
||||||
workers: process.env.CI ? 1 : undefined,
|
|
||||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
|
||||||
reporter: "html",
|
|
||||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
|
||||||
use: {
|
|
||||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
|
||||||
baseURL: "http://127.0.0.1:5173",
|
|
||||||
|
|
||||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
|
||||||
trace: "on-first-retry",
|
|
||||||
|
|
||||||
/* Set default locale to English (US) */
|
|
||||||
locale: "en-US",
|
|
||||||
},
|
|
||||||
|
|
||||||
/* Configure projects for major browsers */
|
|
||||||
projects: [
|
|
||||||
{
|
|
||||||
name: "chromium",
|
|
||||||
use: { ...devices["Desktop Chrome"] },
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: "firefox",
|
|
||||||
use: { ...devices["Desktop Firefox"] },
|
|
||||||
},
|
|
||||||
|
|
||||||
// {
|
|
||||||
// name: "webkit",
|
|
||||||
// use: { ...devices["Desktop Safari"] },
|
|
||||||
// },
|
|
||||||
|
|
||||||
/* Test against mobile viewports. */
|
|
||||||
// {
|
|
||||||
// name: 'Mobile Chrome',
|
|
||||||
// use: { ...devices['Pixel 5'] },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Mobile Safari',
|
|
||||||
// use: { ...devices['iPhone 12'] },
|
|
||||||
// },
|
|
||||||
|
|
||||||
/* Test against branded browsers. */
|
|
||||||
// {
|
|
||||||
// name: 'Microsoft Edge',
|
|
||||||
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'Google Chrome',
|
|
||||||
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
|
|
||||||
// },
|
|
||||||
],
|
|
||||||
|
|
||||||
/* Run your local dev server before starting the tests */
|
|
||||||
webServer: {
|
|
||||||
command: "npm run dev",
|
|
||||||
url: "http://127.0.0.1:5173",
|
|
||||||
reuseExistingServer: !process.env.CI,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
4237
frontend/pnpm-lock.yaml
generated
@@ -1,147 +1 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="560" height="560" version="1.1" id="prefix__svg44" clip-rule="evenodd" fill-rule="evenodd" image-rendering="optimizeQuality" shape-rendering="geometricPrecision" text-rendering="geometricPrecision"><defs id="prefix__defs4"><style type="text/css" id="style2">.prefix__fil1{fill:#fefefe}.prefix__fil6{fill:#006498}.prefix__fil5{fill:#bdeaff}</style></defs><g id="prefix__g85" transform="translate(-70 -70)"><path class="prefix__fil1" d="M350 71c154 0 279 125 279 279S504 629 350 629 71 504 71 350 196 71 350 71z" id="prefix__path9" fill="#fefefe"/><path d="M475 236l118 151c3 116-149 252-292 198l-76-99 114-156s138-95 136-94z" id="prefix__path11" fill="#332c2b" fill-opacity=".149"/><path d="M231 211h208l38 24v246c0 5-3 8-8 8H231c-5 0-8-3-8-8V219c0-5 3-8 8-8z" id="prefix__path13" fill="#2bbcff"/><path d="M231 211h208l38 24v2l-37-23H231c-4 0-7 3-7 7v263c-1-1-1-2-1-3V219c0-5 3-8 8-8z" id="prefix__path15" fill="#53c6fc"/><path class="prefix__fil5" id="prefix__polygon17" fill="#bdeaff" d="M305 212h113v98H305z"/><path class="prefix__fil5" d="M255 363h189c3 0 5 2 5 4v116H250V367c0-2 2-4 5-4z" id="prefix__path19" fill="#bdeaff"/><path class="prefix__fil6" id="prefix__polygon21" fill="#006498" d="M250 470h199v13H250z"/><path class="prefix__fil6" d="M380 226h10c3 0 6 2 6 5v40c0 3-3 6-6 6h-10c-3 0-6-3-6-6v-40c0-3 3-5 6-5z" id="prefix__path23" fill="#006498"/><path class="prefix__fil1" d="M254 226c10 0 17 7 17 17 0 9-7 16-17 16-9 0-17-7-17-16 0-10 8-17 17-17z" id="prefix__path25" fill="#fefefe"/><path class="prefix__fil6" d="M267 448h165c2 0 3 1 3 3 0 1-1 3-3 3H267c-2 0-3-2-3-3 0-2 1-3 3-3z" id="prefix__path27" fill="#006498"/><path class="prefix__fil6" d="M267 415h165c2 0 3 1 3 3 0 1-1 2-3 2H267c-2 0-3-1-3-2 0-2 1-3 3-3z" id="prefix__path29" fill="#006498"/><path class="prefix__fil6" d="M267 381h165c2 0 3 2 3 3 0 2-1 3-3 3H267c-2 0-3-1-3-3 0-1 1-3 3-3z" id="prefix__path31" fill="#006498"/><path class="prefix__fil1" d="M236 472c3 0 5 2 5 5 0 2-2 4-5 4s-5-2-5-4c0-3 2-5 5-5z" id="prefix__path33" fill="#fefefe"/><path class="prefix__fil1" d="M463 472c3 0 5 2 5 5 0 2-2 4-5 4s-5-2-5-4c0-3 2-5 5-5z" id="prefix__path35" fill="#fefefe"/><path class="prefix__fil6" id="prefix__polygon37" fill="#006498" d="M305 212h-21v98h21z"/><path d="M477 479v2c0 5-3 8-8 8H231c-5 0-8-3-8-8v-2c0 4 3 8 8 8h238c5 0 8-4 8-8z" id="prefix__path39" fill="#0ea5eb"/><path d="M350 70c155 0 280 125 280 280S505 630 350 630 70 505 70 350 195 70 350 70zm0 46c129 0 234 105 234 234S479 584 350 584 116 479 116 350s105-234 234-234z" id="prefix__path41" fill="#2979ff"/></g></svg>
|
||||||
<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"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xml:space="preserve"
|
|
||||||
width="560"
|
|
||||||
height="560"
|
|
||||||
version="1.1"
|
|
||||||
style="clip-rule:evenodd;fill-rule:evenodd;image-rendering:optimizeQuality;shape-rendering:geometricPrecision;text-rendering:geometricPrecision"
|
|
||||||
viewBox="0 0 560 560"
|
|
||||||
id="svg44"
|
|
||||||
sodipodi:docname="icon_raw.svg"
|
|
||||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
|
||||||
inkscape:export-filename="/home/umarcor/filebrowser/logo/icon_raw.svg.png"
|
|
||||||
inkscape:export-xdpi="96"
|
|
||||||
inkscape:export-ydpi="96"><metadata
|
|
||||||
id="metadata48"><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 /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1"
|
|
||||||
objecttolerance="10"
|
|
||||||
gridtolerance="10"
|
|
||||||
guidetolerance="10"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:window-width="1366"
|
|
||||||
inkscape:window-height="711"
|
|
||||||
id="namedview46"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="0.33714286"
|
|
||||||
inkscape:cx="-172.33051"
|
|
||||||
inkscape:cy="280"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="20"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="svg44" />
|
|
||||||
<defs
|
|
||||||
id="defs4">
|
|
||||||
<style
|
|
||||||
type="text/css"
|
|
||||||
id="style2">
|
|
||||||
<![CDATA[
|
|
||||||
.fil1 {fill:#FEFEFE}
|
|
||||||
.fil6 {fill:#006498}
|
|
||||||
.fil7 {fill:#0EA5EB}
|
|
||||||
.fil8 {fill:#2979FF}
|
|
||||||
.fil3 {fill:#2BBCFF}
|
|
||||||
.fil0 {fill:#455A64}
|
|
||||||
.fil4 {fill:#53C6FC}
|
|
||||||
.fil5 {fill:#BDEAFF}
|
|
||||||
.fil2 {fill:#332C2B;fill-opacity:0.149020}
|
|
||||||
]]>
|
|
||||||
</style>
|
|
||||||
</defs>
|
|
||||||
<g
|
|
||||||
id="g85"
|
|
||||||
transform="translate(-70,-70)"><path
|
|
||||||
class="fil1"
|
|
||||||
d="M 350,71 C 504,71 629,196 629,350 629,504 504,629 350,629 196,629 71,504 71,350 71,196 196,71 350,71 Z"
|
|
||||||
id="path9"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:#fefefe" /><path
|
|
||||||
class="fil2"
|
|
||||||
d="M 475,236 593,387 C 596,503 444,639 301,585 L 225,486 339,330 c 0,0 138,-95 136,-94 z"
|
|
||||||
id="path11"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:#332c2b;fill-opacity:0.14902003" /><path
|
|
||||||
class="fil3"
|
|
||||||
d="m 231,211 h 208 l 38,24 v 246 c 0,5 -3,8 -8,8 H 231 c -5,0 -8,-3 -8,-8 V 219 c 0,-5 3,-8 8,-8 z"
|
|
||||||
id="path13"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:#2bbcff" /><path
|
|
||||||
class="fil4"
|
|
||||||
d="m 231,211 h 208 l 38,24 v 2 L 440,214 H 231 c -4,0 -7,3 -7,7 v 263 c -1,-1 -1,-2 -1,-3 V 219 c 0,-5 3,-8 8,-8 z"
|
|
||||||
id="path15"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:#53c6fc" /><polygon
|
|
||||||
class="fil5"
|
|
||||||
points="305,212 418,212 418,310 305,310 "
|
|
||||||
id="polygon17"
|
|
||||||
style="fill:#bdeaff" /><path
|
|
||||||
class="fil5"
|
|
||||||
d="m 255,363 h 189 c 3,0 5,2 5,4 V 483 H 250 V 367 c 0,-2 2,-4 5,-4 z"
|
|
||||||
id="path19"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:#bdeaff" /><polygon
|
|
||||||
class="fil6"
|
|
||||||
points="250,470 449,470 449,483 250,483 "
|
|
||||||
id="polygon21"
|
|
||||||
style="fill:#006498" /><path
|
|
||||||
class="fil6"
|
|
||||||
d="m 380,226 h 10 c 3,0 6,2 6,5 v 40 c 0,3 -3,6 -6,6 h -10 c -3,0 -6,-3 -6,-6 v -40 c 0,-3 3,-5 6,-5 z"
|
|
||||||
id="path23"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:#006498" /><path
|
|
||||||
class="fil1"
|
|
||||||
d="m 254,226 c 10,0 17,7 17,17 0,9 -7,16 -17,16 -9,0 -17,-7 -17,-16 0,-10 8,-17 17,-17 z"
|
|
||||||
id="path25"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:#fefefe" /><path
|
|
||||||
class="fil6"
|
|
||||||
d="m 267,448 h 165 c 2,0 3,1 3,3 v 0 c 0,1 -1,3 -3,3 H 267 c -2,0 -3,-2 -3,-3 v 0 c 0,-2 1,-3 3,-3 z"
|
|
||||||
id="path27"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:#006498" /><path
|
|
||||||
class="fil6"
|
|
||||||
d="m 267,415 h 165 c 2,0 3,1 3,3 v 0 c 0,1 -1,2 -3,2 H 267 c -2,0 -3,-1 -3,-2 v 0 c 0,-2 1,-3 3,-3 z"
|
|
||||||
id="path29"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:#006498" /><path
|
|
||||||
class="fil6"
|
|
||||||
d="m 267,381 h 165 c 2,0 3,2 3,3 v 0 c 0,2 -1,3 -3,3 H 267 c -2,0 -3,-1 -3,-3 v 0 c 0,-1 1,-3 3,-3 z"
|
|
||||||
id="path31"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:#006498" /><path
|
|
||||||
class="fil1"
|
|
||||||
d="m 236,472 c 3,0 5,2 5,5 0,2 -2,4 -5,4 -3,0 -5,-2 -5,-4 0,-3 2,-5 5,-5 z"
|
|
||||||
id="path33"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:#fefefe" /><path
|
|
||||||
class="fil1"
|
|
||||||
d="m 463,472 c 3,0 5,2 5,5 0,2 -2,4 -5,4 -3,0 -5,-2 -5,-4 0,-3 2,-5 5,-5 z"
|
|
||||||
id="path35"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:#fefefe" /><polygon
|
|
||||||
class="fil6"
|
|
||||||
points="305,212 284,212 284,310 305,310 "
|
|
||||||
id="polygon37"
|
|
||||||
style="fill:#006498" /><path
|
|
||||||
class="fil7"
|
|
||||||
d="m 477,479 v 2 c 0,5 -3,8 -8,8 H 231 c -5,0 -8,-3 -8,-8 v -2 c 0,4 3,8 8,8 h 238 c 5,0 8,-4 8,-8 z"
|
|
||||||
id="path39"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:#0ea5eb" /><path
|
|
||||||
class="fil8"
|
|
||||||
d="M 350,70 C 505,70 630,195 630,350 630,505 505,630 350,630 195,630 70,505 70,350 70,195 195,70 350,70 Z m 0,46 C 479,116 584,221 584,350 584,479 479,584 350,584 221,584 116,479 116,350 116,221 221,116 350,116 Z"
|
|
||||||
id="path41"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:#2979ff" /></g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 2.6 KiB |
@@ -18,9 +18,17 @@
|
|||||||
|
|
||||||
<meta name="robots" content="noindex,nofollow" />
|
<meta name="robots" content="noindex,nofollow" />
|
||||||
|
|
||||||
<link rel="icon" type="image/svg+xml" href="[{[ .StaticURL ]}]/img/icons/favicon.svg" />
|
<link
|
||||||
|
rel="icon"
|
||||||
|
type="image/svg+xml"
|
||||||
|
href="[{[ .StaticURL ]}]/img/icons/favicon.svg"
|
||||||
|
/>
|
||||||
<link rel="shortcut icon" href="[{[ .StaticURL ]}]/img/icons/favicon.ico" />
|
<link rel="shortcut icon" href="[{[ .StaticURL ]}]/img/icons/favicon.ico" />
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="[{[ .StaticURL ]}]/img/icons/apple-touch-icon.png" />
|
<link
|
||||||
|
rel="apple-touch-icon"
|
||||||
|
sizes="180x180"
|
||||||
|
href="[{[ .StaticURL ]}]/img/icons/apple-touch-icon.png"
|
||||||
|
/>
|
||||||
<meta name="apple-mobile-web-app-title" content="File Browser" />
|
<meta name="apple-mobile-web-app-title" content="File Browser" />
|
||||||
|
|
||||||
<!-- Add to home screen for Android and modern mobile browsers -->
|
<!-- Add to home screen for Android and modern mobile browsers -->
|
||||||
|
|||||||
@@ -91,3 +91,21 @@ export function createURL(endpoint: string, searchParams = {}): string {
|
|||||||
|
|
||||||
return url.toString();
|
return url.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setSafeTimeout(callback: () => void, delay: number): number {
|
||||||
|
const MAX_DELAY = 86_400_000;
|
||||||
|
let remaining = delay;
|
||||||
|
|
||||||
|
function scheduleNext(): number {
|
||||||
|
if (remaining <= MAX_DELAY) {
|
||||||
|
return window.setTimeout(callback, remaining);
|
||||||
|
} else {
|
||||||
|
return window.setTimeout(() => {
|
||||||
|
remaining -= MAX_DELAY;
|
||||||
|
scheduleNext();
|
||||||
|
}, MAX_DELAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return scheduleNext();
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
<!-- This component taken directly from vue-simple-progress
|
|
||||||
since it didnt support Vue 3 but the component itself does
|
|
||||||
https://raw.githubusercontent.com/dzwillia/vue-simple-progress/master/src/components/Progress.vue -->
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
@@ -44,75 +41,54 @@ https://raw.githubusercontent.com/dzwillia/vue-simple-progress/master/src/compon
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
// We're leaving this untouched as you can read in the beginning
|
import { computed } from "vue";
|
||||||
const isNumber = function (n) {
|
|
||||||
return !isNaN(parseFloat(n)) && isFinite(n);
|
const isNumber = (n: number | string): boolean => {
|
||||||
|
return !isNaN(parseFloat(n as string)) && isFinite(n as number);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
const props = withDefaults(
|
||||||
name: "progress-bar",
|
defineProps<{
|
||||||
props: {
|
val?: number;
|
||||||
val: {
|
max?: number;
|
||||||
default: 0,
|
size?: number | string;
|
||||||
},
|
bgColor?: string;
|
||||||
max: {
|
barColor?: string;
|
||||||
default: 100,
|
barTransition?: string;
|
||||||
},
|
barBorderRadius?: number;
|
||||||
size: {
|
spacing?: number;
|
||||||
// either a number (pixel width/height) or 'tiny', 'small',
|
text?: string;
|
||||||
// 'medium', 'large', 'huge', 'massive' for common sizes
|
textAlign?: string;
|
||||||
default: 3,
|
textPosition?: string;
|
||||||
},
|
fontSize?: number;
|
||||||
"bg-color": {
|
textFgColor?: string;
|
||||||
type: String,
|
}>(),
|
||||||
default: "#eee",
|
{
|
||||||
},
|
val: 0,
|
||||||
"bar-color": {
|
max: 100,
|
||||||
type: String,
|
size: 3,
|
||||||
default: "#2196f3", // match .blue color to Material Design's 'Blue 500' color
|
bgColor: "#eee",
|
||||||
},
|
barColor: "#2196f3",
|
||||||
"bar-transition": {
|
barTransition: "all 0.5s ease",
|
||||||
type: String,
|
barBorderRadius: 0,
|
||||||
default: "all 0.5s ease",
|
spacing: 4,
|
||||||
},
|
text: "",
|
||||||
"bar-border-radius": {
|
textAlign: "center",
|
||||||
type: Number,
|
textPosition: "bottom",
|
||||||
default: 0,
|
fontSize: 13,
|
||||||
},
|
textFgColor: "#222",
|
||||||
spacing: {
|
}
|
||||||
type: Number,
|
);
|
||||||
default: 4,
|
|
||||||
},
|
const pct = computed(() => {
|
||||||
text: {
|
const pct = (props.val / props.max) * 100;
|
||||||
type: String,
|
const pctFixed = pct.toFixed(2);
|
||||||
default: "",
|
return Math.min(parseFloat(pctFixed), props.max);
|
||||||
},
|
});
|
||||||
"text-align": {
|
|
||||||
type: String,
|
const size_px = computed(() => {
|
||||||
default: "center", // 'left', 'right'
|
switch (props.size) {
|
||||||
},
|
|
||||||
"text-position": {
|
|
||||||
type: String,
|
|
||||||
default: "bottom", // 'bottom', 'top', 'middle', 'inside'
|
|
||||||
},
|
|
||||||
"font-size": {
|
|
||||||
type: Number,
|
|
||||||
default: 13,
|
|
||||||
},
|
|
||||||
"text-fg-color": {
|
|
||||||
type: String,
|
|
||||||
default: "#222",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
pct() {
|
|
||||||
let pct = (this.val / this.max) * 100;
|
|
||||||
pct = pct.toFixed(2);
|
|
||||||
return Math.min(pct, this.max);
|
|
||||||
},
|
|
||||||
size_px() {
|
|
||||||
switch (this.size) {
|
|
||||||
case "tiny":
|
case "tiny":
|
||||||
return 2;
|
return 2;
|
||||||
case "small":
|
case "small":
|
||||||
@@ -129,10 +105,11 @@ export default {
|
|||||||
return 64;
|
return 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
return isNumber(this.size) ? this.size : 32;
|
return isNumber(props.size) ? (props.size as number) : 32;
|
||||||
},
|
});
|
||||||
text_padding() {
|
|
||||||
switch (this.size) {
|
const text_padding = computed(() => {
|
||||||
|
switch (props.size) {
|
||||||
case "tiny":
|
case "tiny":
|
||||||
case "small":
|
case "small":
|
||||||
case "medium":
|
case "medium":
|
||||||
@@ -140,13 +117,14 @@ export default {
|
|||||||
case "big":
|
case "big":
|
||||||
case "huge":
|
case "huge":
|
||||||
case "massive":
|
case "massive":
|
||||||
return Math.min(Math.max(Math.ceil(this.size_px / 8), 3), 12);
|
return Math.min(Math.max(Math.ceil(size_px.value / 8), 3), 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
return isNumber(this.spacing) ? this.spacing : 4;
|
return isNumber(props.spacing) ? props.spacing : 4;
|
||||||
},
|
});
|
||||||
text_font_size() {
|
|
||||||
switch (this.size) {
|
const text_font_size = computed(() => {
|
||||||
|
switch (props.size) {
|
||||||
case "tiny":
|
case "tiny":
|
||||||
case "small":
|
case "small":
|
||||||
case "medium":
|
case "medium":
|
||||||
@@ -154,72 +132,73 @@ export default {
|
|||||||
case "big":
|
case "big":
|
||||||
case "huge":
|
case "huge":
|
||||||
case "massive":
|
case "massive":
|
||||||
return Math.min(Math.max(Math.ceil(this.size_px * 1.4), 11), 32);
|
return Math.min(Math.max(Math.ceil(size_px.value * 1.4), 11), 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
return isNumber(this.fontSize) ? this.fontSize : 13;
|
return isNumber(props.fontSize) ? props.fontSize : 13;
|
||||||
},
|
});
|
||||||
progress_style() {
|
|
||||||
const style = {
|
const progress_style = computed(() => {
|
||||||
background: this.bgColor,
|
const style: Record<string, string> = {
|
||||||
|
background: props.bgColor,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.textPosition == "middle" || this.textPosition == "inside") {
|
if (props.textPosition == "middle" || props.textPosition == "inside") {
|
||||||
style["position"] = "relative";
|
style["position"] = "relative";
|
||||||
style["min-height"] = this.size_px + "px";
|
style["min-height"] = size_px.value + "px";
|
||||||
style["z-index"] = "-2";
|
style["z-index"] = "-2";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.barBorderRadius > 0) {
|
if (props.barBorderRadius > 0) {
|
||||||
style["border-radius"] = this.barBorderRadius + "px";
|
style["border-radius"] = props.barBorderRadius + "px";
|
||||||
}
|
}
|
||||||
|
|
||||||
return style;
|
return style;
|
||||||
},
|
});
|
||||||
bar_style() {
|
|
||||||
const style = {
|
const bar_style = computed(() => {
|
||||||
background: this.barColor,
|
const style: Record<string, string> = {
|
||||||
width: this.pct + "%",
|
background: props.barColor,
|
||||||
height: this.size_px + "px",
|
width: pct.value + "%",
|
||||||
transition: this.barTransition,
|
height: size_px.value + "px",
|
||||||
|
transition: props.barTransition,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.barBorderRadius > 0) {
|
if (props.barBorderRadius > 0) {
|
||||||
style["border-radius"] = this.barBorderRadius + "px";
|
style["border-radius"] = props.barBorderRadius + "px";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.textPosition == "middle" || this.textPosition == "inside") {
|
if (props.textPosition == "middle" || props.textPosition == "inside") {
|
||||||
style["position"] = "absolute";
|
style["position"] = "absolute";
|
||||||
style["top"] = "0";
|
style["top"] = "0";
|
||||||
style["height"] = "100%";
|
style["height"] = "100%";
|
||||||
((style["min-height"] = this.size_px + "px"),
|
style["min-height"] = size_px.value + "px";
|
||||||
(style["z-index"] = "-1"));
|
style["z-index"] = "-1";
|
||||||
}
|
}
|
||||||
|
|
||||||
return style;
|
return style;
|
||||||
},
|
});
|
||||||
text_style() {
|
|
||||||
const style = {
|
const text_style = computed(() => {
|
||||||
color: this.textFgColor,
|
const style: Record<string, string> = {
|
||||||
"font-size": this.text_font_size + "px",
|
color: props.textFgColor,
|
||||||
"text-align": this.textAlign,
|
"font-size": text_font_size.value + "px",
|
||||||
|
"text-align": props.textAlign,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.textPosition == "top" ||
|
props.textPosition == "top" ||
|
||||||
this.textPosition == "middle" ||
|
props.textPosition == "middle" ||
|
||||||
this.textPosition == "inside"
|
props.textPosition == "inside"
|
||||||
)
|
)
|
||||||
style["padding-bottom"] = this.text_padding + "px";
|
style["padding-bottom"] = text_padding.value + "px";
|
||||||
if (
|
if (
|
||||||
this.textPosition == "bottom" ||
|
props.textPosition == "bottom" ||
|
||||||
this.textPosition == "middle" ||
|
props.textPosition == "middle" ||
|
||||||
this.textPosition == "inside"
|
props.textPosition == "inside"
|
||||||
)
|
)
|
||||||
style["padding-top"] = this.text_padding + "px";
|
style["padding-top"] = text_padding.value + "px";
|
||||||
|
|
||||||
return style;
|
return style;
|
||||||
},
|
});
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
<div
|
<div
|
||||||
class="shell"
|
class="shell"
|
||||||
:class="{ ['shell--hidden']: !showShell }"
|
:class="{ ['shell--hidden']: !showShell }"
|
||||||
:style="{ height: `${this.shellHeight}em`, direction: 'ltr' }"
|
:style="{ height: `${shellHeight}em`, direction: 'ltr' }"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@pointerdown="startDrag()"
|
@pointerdown="startDrag()"
|
||||||
@pointerup="stopDrag()"
|
@pointerup="stopDrag()"
|
||||||
class="shell__divider"
|
class="shell__divider"
|
||||||
:style="this.shellDrag ? { background: `${checkTheme()}` } : ''"
|
:style="shellDrag ? { background: `${checkTheme()}` } : ''"
|
||||||
></div>
|
></div>
|
||||||
<div @click="focus" class="shell__content" ref="scrollable">
|
<div @click="focus" class="shell__content" ref="scrollable">
|
||||||
<div v-for="(c, index) in content" :key="index" class="shell__result">
|
<div v-for="(c, index) in content" :key="index" class="shell__result">
|
||||||
@@ -39,13 +39,15 @@
|
|||||||
<div
|
<div
|
||||||
@pointerup="stopDrag()"
|
@pointerup="stopDrag()"
|
||||||
class="shell__overlay"
|
class="shell__overlay"
|
||||||
v-show="this.shellDrag"
|
v-show="shellDrag"
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { mapState, mapActions } from "pinia";
|
import { ref, computed, onMounted, onBeforeUnmount } from "vue";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
import { useFileStore } from "@/stores/file";
|
import { useFileStore } from "@/stores/file";
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
|
|
||||||
@@ -53,142 +55,164 @@ import { commands } from "@/api";
|
|||||||
import { throttle } from "lodash-es";
|
import { throttle } from "lodash-es";
|
||||||
import { theme } from "@/utils/constants";
|
import { theme } from "@/utils/constants";
|
||||||
|
|
||||||
export default {
|
const route = useRoute();
|
||||||
name: "shell",
|
|
||||||
computed: {
|
|
||||||
...mapState(useLayoutStore, ["showShell"]),
|
|
||||||
...mapState(useFileStore, ["isFiles"]),
|
|
||||||
path: function () {
|
|
||||||
if (this.isFiles) {
|
|
||||||
return this.$route.path;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const fileStore = useFileStore();
|
||||||
|
const layoutStore = useLayoutStore();
|
||||||
|
|
||||||
|
const { showShell } = storeToRefs(layoutStore);
|
||||||
|
const { isFiles } = storeToRefs(fileStore);
|
||||||
|
const { toggleShell } = layoutStore;
|
||||||
|
|
||||||
|
const scrollable = ref<HTMLElement | null>(null);
|
||||||
|
const input = ref<HTMLElement | null>(null);
|
||||||
|
|
||||||
|
const content = ref<Array<{ text: string }>>([]);
|
||||||
|
const history = ref<string[]>([]);
|
||||||
|
const historyPos = ref(0);
|
||||||
|
const canInput = ref(true);
|
||||||
|
const shellDrag = ref(false);
|
||||||
|
const shellHeight = ref(25);
|
||||||
|
const fontsize = ref(
|
||||||
|
parseFloat(getComputedStyle(document.documentElement).fontSize)
|
||||||
|
);
|
||||||
|
|
||||||
|
const path = computed(() => {
|
||||||
|
if (isFiles.value) {
|
||||||
|
return route.path;
|
||||||
|
}
|
||||||
return "";
|
return "";
|
||||||
},
|
});
|
||||||
},
|
|
||||||
data: () => ({
|
const checkTheme = () => {
|
||||||
content: [],
|
|
||||||
history: [],
|
|
||||||
historyPos: 0,
|
|
||||||
canInput: true,
|
|
||||||
shellDrag: false,
|
|
||||||
shellHeight: 25,
|
|
||||||
fontsize: parseFloat(getComputedStyle(document.documentElement).fontSize),
|
|
||||||
}),
|
|
||||||
mounted() {
|
|
||||||
window.addEventListener("resize", this.resize);
|
|
||||||
},
|
|
||||||
beforeUnmount() {
|
|
||||||
window.removeEventListener("resize", this.resize);
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions(useLayoutStore, ["toggleShell"]),
|
|
||||||
checkTheme() {
|
|
||||||
if (theme == "dark") {
|
if (theme == "dark") {
|
||||||
return "rgba(255, 255, 255, 0.4)";
|
return "rgba(255, 255, 255, 0.4)";
|
||||||
}
|
}
|
||||||
return "rgba(127, 127, 127, 0.4)";
|
return "rgba(127, 127, 127, 0.4)";
|
||||||
},
|
};
|
||||||
startDrag() {
|
|
||||||
document.addEventListener("pointermove", this.handleDrag);
|
const scroll = () => {
|
||||||
this.shellDrag = true;
|
if (scrollable.value) {
|
||||||
},
|
scrollable.value.scrollTop = scrollable.value.scrollHeight;
|
||||||
stopDrag() {
|
}
|
||||||
document.removeEventListener("pointermove", this.handleDrag);
|
};
|
||||||
this.shellDrag = false;
|
|
||||||
},
|
const focus = () => {
|
||||||
handleDrag: throttle(function (event) {
|
input.value?.focus();
|
||||||
const top = window.innerHeight / this.fontsize - 4;
|
};
|
||||||
const userPos = (window.innerHeight - event.clientY) / this.fontsize;
|
|
||||||
const bottom =
|
const handleDrag = throttle((event: PointerEvent) => {
|
||||||
2.25 +
|
const top = window.innerHeight / fontsize.value - 4;
|
||||||
document.querySelector(".shell__divider").offsetHeight / this.fontsize;
|
const userPos = (window.innerHeight - event.clientY) / fontsize.value;
|
||||||
|
const divider = document.querySelector(".shell__divider") as HTMLElement;
|
||||||
|
const bottom = 2.25 + (divider?.offsetHeight ?? 0) / fontsize.value;
|
||||||
|
|
||||||
if (userPos <= top && userPos >= bottom) {
|
if (userPos <= top && userPos >= bottom) {
|
||||||
this.shellHeight = userPos.toFixed(2);
|
shellHeight.value = parseFloat(userPos.toFixed(2));
|
||||||
}
|
}
|
||||||
}, 32),
|
}, 32);
|
||||||
resize: throttle(function () {
|
|
||||||
const top = window.innerHeight / this.fontsize - 4;
|
|
||||||
const bottom =
|
|
||||||
2.25 +
|
|
||||||
document.querySelector(".shell__divider").offsetHeight / this.fontsize;
|
|
||||||
|
|
||||||
if (this.shellHeight > top) {
|
const resize = throttle(() => {
|
||||||
this.shellHeight = top;
|
const top = window.innerHeight / fontsize.value - 4;
|
||||||
} else if (this.shellHeight < bottom) {
|
const divider = document.querySelector(".shell__divider") as HTMLElement;
|
||||||
this.shellHeight = bottom;
|
const bottom = 2.25 + (divider?.offsetHeight ?? 0) / fontsize.value;
|
||||||
|
|
||||||
|
if (shellHeight.value > top) {
|
||||||
|
shellHeight.value = top;
|
||||||
|
} else if (shellHeight.value < bottom) {
|
||||||
|
shellHeight.value = bottom;
|
||||||
}
|
}
|
||||||
}, 32),
|
}, 32);
|
||||||
scroll: function () {
|
|
||||||
this.$refs.scrollable.scrollTop = this.$refs.scrollable.scrollHeight;
|
const startDrag = () => {
|
||||||
},
|
document.addEventListener("pointermove", handleDrag as any);
|
||||||
focus: function () {
|
shellDrag.value = true;
|
||||||
this.$refs.input.focus();
|
};
|
||||||
},
|
|
||||||
historyUp() {
|
const stopDrag = () => {
|
||||||
if (this.historyPos > 0) {
|
document.removeEventListener("pointermove", handleDrag as any);
|
||||||
this.$refs.input.innerText = this.history[--this.historyPos];
|
shellDrag.value = false;
|
||||||
this.focus();
|
};
|
||||||
|
|
||||||
|
const historyUp = () => {
|
||||||
|
if (historyPos.value > 0 && input.value) {
|
||||||
|
historyPos.value--;
|
||||||
|
input.value.innerText = history.value[historyPos.value];
|
||||||
|
focus();
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
historyDown() {
|
|
||||||
if (this.historyPos >= 0 && this.historyPos < this.history.length - 1) {
|
const historyDown = () => {
|
||||||
this.$refs.input.innerText = this.history[++this.historyPos];
|
if (
|
||||||
this.focus();
|
historyPos.value >= 0 &&
|
||||||
|
historyPos.value < history.value.length - 1 &&
|
||||||
|
input.value
|
||||||
|
) {
|
||||||
|
historyPos.value++;
|
||||||
|
input.value.innerText = history.value[historyPos.value];
|
||||||
|
focus();
|
||||||
} else {
|
} else {
|
||||||
this.historyPos = this.history.length;
|
historyPos.value = history.value.length;
|
||||||
this.$refs.input.innerText = "";
|
if (input.value) {
|
||||||
|
input.value.innerText = "";
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
submit: function (event) {
|
};
|
||||||
const cmd = event.target.innerText.trim();
|
|
||||||
|
const submit = (event: Event) => {
|
||||||
|
const target = event.target as HTMLElement;
|
||||||
|
const cmd = target.innerText.trim();
|
||||||
|
|
||||||
if (cmd === "") {
|
if (cmd === "") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd === "clear") {
|
if (cmd === "clear") {
|
||||||
this.content = [];
|
content.value = [];
|
||||||
event.target.innerHTML = "";
|
target.innerHTML = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd === "exit") {
|
if (cmd === "exit") {
|
||||||
event.target.innerHTML = "";
|
target.innerHTML = "";
|
||||||
this.toggleShell();
|
toggleShell();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.canInput = false;
|
canInput.value = false;
|
||||||
event.target.innerHTML = "";
|
target.innerHTML = "";
|
||||||
|
|
||||||
const results = {
|
const results = {
|
||||||
text: `${cmd}\n\n`,
|
text: `${cmd}\n\n`,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.history.push(cmd);
|
history.value.push(cmd);
|
||||||
this.historyPos = this.history.length;
|
historyPos.value = history.value.length;
|
||||||
this.content.push(results);
|
content.value.push(results);
|
||||||
|
|
||||||
commands(
|
commands(
|
||||||
this.path,
|
path.value,
|
||||||
cmd,
|
cmd,
|
||||||
(event) => {
|
(event: MessageEvent) => {
|
||||||
results.text += `${event.data}\n`;
|
results.text += `${event.data}\n`;
|
||||||
this.scroll();
|
scroll();
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
results.text = results.text
|
results.text = results.text
|
||||||
|
|
||||||
.replace(/\u001b\[[0-9;]+m/g, "") // Filter ANSI color for now
|
.replace(/\u001b\[[0-9;]+m/g, "") // Filter ANSI color for now
|
||||||
.trimEnd();
|
.trimEnd();
|
||||||
this.canInput = true;
|
canInput.value = true;
|
||||||
this.$refs.input.focus();
|
input.value?.focus();
|
||||||
this.scroll();
|
scroll();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
window.addEventListener("resize", resize as any);
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
window.removeEventListener("resize", resize as any);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<template v-if="isLoggedIn">
|
<template v-if="isLoggedIn">
|
||||||
<button @click="toAccountSettings" class="action">
|
<button @click="toAccountSettings" class="action">
|
||||||
<i class="material-icons">person</i>
|
<i class="material-icons">person</i>
|
||||||
<span>{{ user.username }}</span>
|
<span>{{ user?.username }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="action"
|
class="action"
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
<span>{{ $t("sidebar.myFiles") }}</span>
|
<span>{{ $t("sidebar.myFiles") }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div v-if="user.perm.create">
|
<div v-if="user?.perm.create">
|
||||||
<button
|
<button
|
||||||
@click="showHover('newDir')"
|
@click="showHover('newDir')"
|
||||||
class="action"
|
class="action"
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="user.perm.admin">
|
<div v-if="user?.perm.admin">
|
||||||
<button
|
<button
|
||||||
class="action"
|
class="action"
|
||||||
@click="toGlobalSettings"
|
@click="toGlobalSettings"
|
||||||
@@ -113,9 +113,10 @@
|
|||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { reactive } from "vue";
|
import { reactive, ref, computed, watch, onUnmounted } from "vue";
|
||||||
import { mapActions, mapState } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import { useAuthStore } from "@/stores/auth";
|
import { useAuthStore } from "@/stores/auth";
|
||||||
import { useFileStore } from "@/stores/file";
|
import { useFileStore } from "@/stores/file";
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
@@ -135,84 +136,85 @@ import prettyBytes from "pretty-bytes";
|
|||||||
|
|
||||||
const USAGE_DEFAULT = { used: "0 B", total: "0 B", usedPercentage: 0 };
|
const USAGE_DEFAULT = { used: "0 B", total: "0 B", usedPercentage: 0 };
|
||||||
|
|
||||||
export default {
|
const route = useRoute();
|
||||||
name: "sidebar",
|
const router = useRouter();
|
||||||
setup() {
|
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
const fileStore = useFileStore();
|
||||||
|
const layoutStore = useLayoutStore();
|
||||||
|
|
||||||
|
const { user, isLoggedIn } = storeToRefs(authStore);
|
||||||
|
const { isFiles } = storeToRefs(fileStore);
|
||||||
|
const { currentPromptName } = storeToRefs(layoutStore);
|
||||||
|
const { closeHovers, showHover } = layoutStore;
|
||||||
|
|
||||||
const usage = reactive(USAGE_DEFAULT);
|
const usage = reactive(USAGE_DEFAULT);
|
||||||
return { usage, usageAbortController: new AbortController() };
|
const usageAbortController = ref(new AbortController());
|
||||||
},
|
|
||||||
components: {
|
const active = computed(() => {
|
||||||
ProgressBar,
|
return currentPromptName.value === "sidebar";
|
||||||
},
|
});
|
||||||
inject: ["$showError"],
|
|
||||||
computed: {
|
const canLogout = !noAuth && loginPage;
|
||||||
...mapState(useAuthStore, ["user", "isLoggedIn"]),
|
|
||||||
...mapState(useFileStore, ["isFiles", "reload"]),
|
const abortOngoingFetchUsage = () => {
|
||||||
...mapState(useLayoutStore, ["currentPromptName"]),
|
usageAbortController.value.abort();
|
||||||
active() {
|
};
|
||||||
return this.currentPromptName === "sidebar";
|
|
||||||
},
|
const fetchUsage = async () => {
|
||||||
signup: () => signup,
|
const path = route.path.endsWith("/") ? route.path : route.path + "/";
|
||||||
version: () => version,
|
|
||||||
disableExternal: () => disableExternal,
|
|
||||||
disableUsedPercentage: () => disableUsedPercentage,
|
|
||||||
canLogout: () => !noAuth && loginPage,
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions(useLayoutStore, ["closeHovers", "showHover"]),
|
|
||||||
abortOngoingFetchUsage() {
|
|
||||||
this.usageAbortController.abort();
|
|
||||||
},
|
|
||||||
async fetchUsage() {
|
|
||||||
const path = this.$route.path.endsWith("/")
|
|
||||||
? this.$route.path
|
|
||||||
: this.$route.path + "/";
|
|
||||||
let usageStats = USAGE_DEFAULT;
|
let usageStats = USAGE_DEFAULT;
|
||||||
if (this.disableUsedPercentage) {
|
if (disableUsedPercentage) {
|
||||||
return Object.assign(this.usage, usageStats);
|
return Object.assign(usage, usageStats);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
this.abortOngoingFetchUsage();
|
abortOngoingFetchUsage();
|
||||||
this.usageAbortController = new AbortController();
|
usageAbortController.value = new AbortController();
|
||||||
const usage = await api.usage(path, this.usageAbortController.signal);
|
const usageData = await api.usage(path, usageAbortController.value.signal);
|
||||||
usageStats = {
|
usageStats = {
|
||||||
used: prettyBytes(usage.used, { binary: true }),
|
used: prettyBytes(usageData.used, { binary: true }),
|
||||||
total: prettyBytes(usage.total, { binary: true }),
|
total: prettyBytes(usageData.total, { binary: true }),
|
||||||
usedPercentage: Math.round((usage.used / usage.total) * 100),
|
usedPercentage: Math.round((usageData.used / usageData.total) * 100),
|
||||||
};
|
};
|
||||||
} finally {
|
} finally {
|
||||||
return Object.assign(this.usage, usageStats);
|
return Object.assign(usage, usageStats);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
toRoot() {
|
|
||||||
this.$router.push({ path: "/files" });
|
|
||||||
this.closeHovers();
|
|
||||||
},
|
|
||||||
toAccountSettings() {
|
|
||||||
this.$router.push({ path: "/settings/profile" });
|
|
||||||
this.closeHovers();
|
|
||||||
},
|
|
||||||
toGlobalSettings() {
|
|
||||||
this.$router.push({ path: "/settings/global" });
|
|
||||||
this.closeHovers();
|
|
||||||
},
|
|
||||||
help() {
|
|
||||||
this.showHover("help");
|
|
||||||
},
|
|
||||||
logout: auth.logout,
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
$route: {
|
|
||||||
handler(to) {
|
|
||||||
if (to.path.includes("/files")) {
|
|
||||||
this.fetchUsage();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
immediate: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
unmounted() {
|
|
||||||
this.abortOngoingFetchUsage();
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const toRoot = () => {
|
||||||
|
router.push({ path: "/files" });
|
||||||
|
closeHovers();
|
||||||
|
};
|
||||||
|
|
||||||
|
const toAccountSettings = () => {
|
||||||
|
router.push({ path: "/settings/profile" });
|
||||||
|
closeHovers();
|
||||||
|
};
|
||||||
|
|
||||||
|
const toGlobalSettings = () => {
|
||||||
|
router.push({ path: "/settings/global" });
|
||||||
|
closeHovers();
|
||||||
|
};
|
||||||
|
|
||||||
|
const help = () => {
|
||||||
|
showHover("help");
|
||||||
|
};
|
||||||
|
|
||||||
|
const logout = () => {
|
||||||
|
auth.logout();
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => route.path,
|
||||||
|
(newPath) => {
|
||||||
|
if (newPath.includes("/files")) {
|
||||||
|
fetchUsage();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
abortOngoingFetchUsage();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<p>{{ $t("prompts.copyMessage") }}</p>
|
<p>{{ $t("prompts.copyMessage") }}</p>
|
||||||
<file-list
|
<file-list
|
||||||
ref="fileList"
|
ref="fileList"
|
||||||
@update:selected="(val) => (dest = val)"
|
@update:selected="(val: string) => (dest = val)"
|
||||||
tabindex="1"
|
tabindex="1"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -17,10 +17,10 @@
|
|||||||
class="card-action"
|
class="card-action"
|
||||||
style="display: flex; align-items: center; justify-content: space-between"
|
style="display: flex; align-items: center; justify-content: space-between"
|
||||||
>
|
>
|
||||||
<template v-if="user.perm.create">
|
<template v-if="user?.perm.create">
|
||||||
<button
|
<button
|
||||||
class="button button--flat"
|
class="button button--flat"
|
||||||
@click="$refs.fileList.createDir()"
|
@click="fileList?.createDir()"
|
||||||
:aria-label="$t('sidebar.newFolder')"
|
:aria-label="$t('sidebar.newFolder')"
|
||||||
:title="$t('sidebar.newFolder')"
|
:title="$t('sidebar.newFolder')"
|
||||||
style="justify-self: left"
|
style="justify-self: left"
|
||||||
@@ -53,8 +53,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { mapActions, mapState, mapWritableState } from "pinia";
|
import { ref, inject } from "vue";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import { useFileStore } from "@/stores/file";
|
import { useFileStore } from "@/stores/file";
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
import { useAuthStore } from "@/stores/auth";
|
import { useAuthStore } from "@/stores/auth";
|
||||||
@@ -64,81 +66,77 @@ import buttons from "@/utils/buttons";
|
|||||||
import * as upload from "@/utils/upload";
|
import * as upload from "@/utils/upload";
|
||||||
import { removePrefix } from "@/api/utils";
|
import { removePrefix } from "@/api/utils";
|
||||||
|
|
||||||
export default {
|
const route = useRoute();
|
||||||
name: "copy",
|
const router = useRouter();
|
||||||
components: { FileList },
|
const $showError = inject<(error: unknown) => void>("$showError");
|
||||||
data: function () {
|
|
||||||
return {
|
const fileStore = useFileStore();
|
||||||
current: window.location.pathname,
|
const layoutStore = useLayoutStore();
|
||||||
dest: null,
|
const authStore = useAuthStore();
|
||||||
};
|
|
||||||
},
|
const { req, selected } = storeToRefs(fileStore);
|
||||||
inject: ["$showError"],
|
const { user } = storeToRefs(authStore);
|
||||||
computed: {
|
const { showHover, closeHovers } = layoutStore;
|
||||||
...mapState(useFileStore, ["req", "selected"]),
|
|
||||||
...mapState(useAuthStore, ["user"]),
|
const fileList = ref<InstanceType<typeof FileList> | null>(null);
|
||||||
...mapWritableState(useFileStore, ["reload", "preselect"]),
|
const dest = ref<string | null>(null);
|
||||||
},
|
|
||||||
methods: {
|
const copy = async (event: Event) => {
|
||||||
...mapActions(useLayoutStore, ["showHover", "closeHovers"]),
|
|
||||||
copy: async function (event) {
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const items = [];
|
const items: Array<{ from: string; to: string; name: string }> = [];
|
||||||
|
|
||||||
// Create a new promise for each file.
|
// Create a new promise for each file.
|
||||||
for (const item of this.selected) {
|
for (const item of selected.value) {
|
||||||
items.push({
|
items.push({
|
||||||
from: this.req.items[item].url,
|
from: req.value!.items[item].url,
|
||||||
to: this.dest + encodeURIComponent(this.req.items[item].name),
|
to: dest.value! + encodeURIComponent(req.value!.items[item].name),
|
||||||
name: this.req.items[item].name,
|
name: req.value!.items[item].name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const action = async (overwrite, rename) => {
|
const action = async (overwrite: boolean, rename: boolean) => {
|
||||||
buttons.loading("copy");
|
buttons.loading("copy");
|
||||||
|
|
||||||
await api
|
await api
|
||||||
.copy(items, overwrite, rename)
|
.copy(items, overwrite, rename)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
buttons.success("copy");
|
buttons.success("copy");
|
||||||
this.preselect = removePrefix(items[0].to);
|
fileStore.preselect = removePrefix(items[0].to);
|
||||||
|
|
||||||
if (this.$route.path === this.dest) {
|
|
||||||
this.reload = true;
|
|
||||||
|
|
||||||
|
if (route.path === dest.value) {
|
||||||
|
fileStore.reload = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$router.push({ path: this.dest });
|
router.push({ path: dest.value! });
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
buttons.done("copy");
|
buttons.done("copy");
|
||||||
this.$showError(e);
|
$showError?.(e);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.$route.path === this.dest) {
|
if (route.path === dest.value) {
|
||||||
this.closeHovers();
|
closeHovers();
|
||||||
action(false, true);
|
action(false, true);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dstItems = (await api.fetch(this.dest)).items;
|
const dstItems = (await api.fetch(dest.value!)).items;
|
||||||
const conflict = upload.checkConflict(items, dstItems);
|
const conflict = upload.checkConflict(items as any, dstItems);
|
||||||
|
|
||||||
let overwrite = false;
|
let overwrite = false;
|
||||||
let rename = false;
|
let rename = false;
|
||||||
|
|
||||||
if (conflict) {
|
if (conflict) {
|
||||||
this.showHover({
|
showHover({
|
||||||
prompt: "replace-rename",
|
prompt: "replace-rename",
|
||||||
confirm: (event, option) => {
|
confirm: (event: Event, option: string) => {
|
||||||
overwrite = option == "overwrite";
|
overwrite = option == "overwrite";
|
||||||
rename = option == "rename";
|
rename = option == "rename";
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.closeHovers();
|
closeHovers();
|
||||||
action(overwrite, rename);
|
action(overwrite, rename);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -147,7 +145,5 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
action(overwrite, rename);
|
action(overwrite, rename);
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
86
frontend/src/components/prompts/CreateFilePath.vue
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="path-container" ref="container">
|
||||||
|
<template v-for="(item, index) in path" :key="index">
|
||||||
|
/
|
||||||
|
<span class="path-item">
|
||||||
|
<span
|
||||||
|
v-if="isDir === true || index < path.length - 1"
|
||||||
|
class="material-icons"
|
||||||
|
>folder
|
||||||
|
</span>
|
||||||
|
<span v-else class="material-icons">insert_drive_file</span>
|
||||||
|
{{ item }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, computed, watch, nextTick, defineProps } from "vue";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
import { useFileStore } from "@/stores/file";
|
||||||
|
import url from "@/utils/url";
|
||||||
|
|
||||||
|
const fileStore = useFileStore();
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
isDir: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const container = ref<HTMLElement | null>(null);
|
||||||
|
|
||||||
|
const path = computed(() => {
|
||||||
|
let basePath = fileStore.isFiles ? route.path : url.removeLastDir(route.path);
|
||||||
|
if (!basePath.endsWith("/")) {
|
||||||
|
basePath += "/";
|
||||||
|
}
|
||||||
|
basePath += props.name;
|
||||||
|
return basePath.split("/").filter(Boolean).splice(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(path, () => {
|
||||||
|
nextTick(() => {
|
||||||
|
const lastItem = container.value?.lastElementChild;
|
||||||
|
lastItem?.scrollIntoView({ behavior: "auto", inline: "end" });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.path-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0.2em 0;
|
||||||
|
gap: 0.25em;
|
||||||
|
overflow-x: auto;
|
||||||
|
max-width: 100%;
|
||||||
|
scrollbar-width: none;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.path-container::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.path-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0.2em 0;
|
||||||
|
gap: 0.25em;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.path-item > span {
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="card floating">
|
<div class="card floating">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<p v-if="!this.isListing || selectedCount === 1">
|
<p v-if="!isListing || selectedCount === 1">
|
||||||
{{ $t("prompts.deleteMessageSingle") }}
|
{{ $t("prompts.deleteMessageSingle") }}
|
||||||
</p>
|
</p>
|
||||||
<p v-else>
|
<p v-else>
|
||||||
@@ -32,67 +32,62 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { mapActions, mapState, mapWritableState } from "pinia";
|
import { inject } from "vue";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
import { files as api } from "@/api";
|
import { files as api } from "@/api";
|
||||||
import buttons from "@/utils/buttons";
|
import buttons from "@/utils/buttons";
|
||||||
import { useFileStore } from "@/stores/file";
|
import { useFileStore } from "@/stores/file";
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
|
|
||||||
export default {
|
const route = useRoute();
|
||||||
name: "delete",
|
const $showError = inject<(error: unknown) => void>("$showError");
|
||||||
inject: ["$showError"],
|
|
||||||
computed: {
|
const fileStore = useFileStore();
|
||||||
...mapState(useFileStore, [
|
const layoutStore = useLayoutStore();
|
||||||
"isListing",
|
|
||||||
"selectedCount",
|
const { isListing, selectedCount, req, selected } = storeToRefs(fileStore);
|
||||||
"req",
|
const { currentPrompt } = storeToRefs(layoutStore);
|
||||||
"selected",
|
const { closeHovers } = layoutStore;
|
||||||
]),
|
|
||||||
...mapState(useLayoutStore, ["currentPrompt"]),
|
const submit = async () => {
|
||||||
...mapWritableState(useFileStore, ["reload", "preselect"]),
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions(useLayoutStore, ["closeHovers"]),
|
|
||||||
submit: async function () {
|
|
||||||
buttons.loading("delete");
|
buttons.loading("delete");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!this.isListing) {
|
if (!isListing.value) {
|
||||||
await api.remove(this.$route.path);
|
await api.remove(route.path);
|
||||||
buttons.success("delete");
|
buttons.success("delete");
|
||||||
|
|
||||||
this.currentPrompt?.confirm();
|
currentPrompt.value?.confirm();
|
||||||
this.closeHovers();
|
closeHovers();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.closeHovers();
|
closeHovers();
|
||||||
|
|
||||||
if (this.selectedCount === 0) {
|
if (selectedCount.value === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const promises = [];
|
const promises = [];
|
||||||
for (const index of this.selected) {
|
for (const index of selected.value) {
|
||||||
promises.push(api.remove(this.req.items[index].url));
|
promises.push(api.remove(req.value!.items[index].url));
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
buttons.success("delete");
|
buttons.success("delete");
|
||||||
|
|
||||||
const nearbyItem =
|
const nearbyItem =
|
||||||
this.req.items[Math.max(0, Math.min(this.selected) - 1)];
|
req.value!.items[Math.max(0, Math.min(...selected.value) - 1)];
|
||||||
|
|
||||||
this.preselect = nearbyItem?.path;
|
fileStore.preselect = nearbyItem?.path;
|
||||||
|
|
||||||
this.reload = true;
|
fileStore.reload = true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
buttons.done("delete");
|
buttons.done("delete");
|
||||||
this.$showError(e);
|
$showError?.(e);
|
||||||
if (this.isListing) this.reload = true;
|
if (isListing.value) fileStore.reload = true;
|
||||||
}
|
}
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -33,8 +33,4 @@ import { useI18n } from "vue-i18n";
|
|||||||
const layoutStore = useLayoutStore();
|
const layoutStore = useLayoutStore();
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
// const emit = defineEmits<{
|
|
||||||
// (e: "confirm"): void;
|
|
||||||
// }>();
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -11,17 +11,26 @@
|
|||||||
@click="closeHovers"
|
@click="closeHovers"
|
||||||
:aria-label="$t('buttons.cancel')"
|
:aria-label="$t('buttons.cancel')"
|
||||||
:title="$t('buttons.cancel')"
|
:title="$t('buttons.cancel')"
|
||||||
tabindex="2"
|
tabindex="3"
|
||||||
>
|
>
|
||||||
{{ $t("buttons.cancel") }}
|
{{ $t("buttons.cancel") }}
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
class="button button--flat button--blue"
|
||||||
|
@click="currentPrompt?.saveAction"
|
||||||
|
:aria-label="$t('buttons.saveChanges')"
|
||||||
|
:title="$t('buttons.saveChanges')"
|
||||||
|
tabindex="1"
|
||||||
|
>
|
||||||
|
{{ $t("buttons.saveChanges") }}
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
id="focus-prompt"
|
id="focus-prompt"
|
||||||
@click="currentPrompt.confirm"
|
@click="currentPrompt?.confirm"
|
||||||
class="button button--flat button--red"
|
class="button button--flat button--red"
|
||||||
:aria-label="$t('buttons.discardChanges')"
|
:aria-label="$t('buttons.discardChanges')"
|
||||||
:title="$t('buttons.discardChanges')"
|
:title="$t('buttons.discardChanges')"
|
||||||
tabindex="1"
|
tabindex="2"
|
||||||
>
|
>
|
||||||
{{ $t("buttons.discardChanges") }}
|
{{ $t("buttons.discardChanges") }}
|
||||||
</button>
|
</button>
|
||||||
@@ -29,17 +38,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { mapState, mapActions } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
|
|
||||||
export default {
|
const layoutStore = useLayoutStore();
|
||||||
name: "discardEditorChanges",
|
const { currentPrompt } = storeToRefs(layoutStore);
|
||||||
computed: {
|
const { closeHovers } = layoutStore;
|
||||||
...mapState(useLayoutStore, ["currentPrompt"]),
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions(useLayoutStore, ["closeHovers"]),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -24,155 +24,174 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { mapState } from "pinia";
|
import { ref, computed, inject, onMounted, onUnmounted } from "vue";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
import { useAuthStore } from "@/stores/auth";
|
import { useAuthStore } from "@/stores/auth";
|
||||||
import { useFileStore } from "@/stores/file";
|
import { useFileStore } from "@/stores/file";
|
||||||
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
|
|
||||||
import url from "@/utils/url";
|
import url from "@/utils/url";
|
||||||
import { files } from "@/api";
|
import { files } from "@/api";
|
||||||
import { StatusError } from "@/api/utils.js";
|
import { StatusError } from "@/api/utils.js";
|
||||||
|
|
||||||
export default {
|
const props = defineProps<{
|
||||||
name: "file-list",
|
exclude?: string[];
|
||||||
props: {
|
}>();
|
||||||
exclude: {
|
|
||||||
type: Array,
|
const emit = defineEmits<{
|
||||||
default: () => [],
|
"update:selected": [value: string];
|
||||||
},
|
}>();
|
||||||
},
|
|
||||||
data: function () {
|
const route = useRoute();
|
||||||
return {
|
const $showError = inject<(error: unknown) => void>("$showError");
|
||||||
items: [],
|
|
||||||
touches: {
|
const authStore = useAuthStore();
|
||||||
|
const fileStore = useFileStore();
|
||||||
|
const layoutStore = useLayoutStore();
|
||||||
|
|
||||||
|
const { user } = storeToRefs(authStore);
|
||||||
|
const { req } = storeToRefs(fileStore);
|
||||||
|
const { showHover } = layoutStore;
|
||||||
|
|
||||||
|
const items = ref<Array<{ name: string; url: string }>>([]);
|
||||||
|
const touches = ref({
|
||||||
id: "",
|
id: "",
|
||||||
count: 0,
|
count: 0,
|
||||||
},
|
});
|
||||||
selected: null,
|
const selected = ref<string | null>(null);
|
||||||
current: window.location.pathname,
|
const current = ref(window.location.pathname);
|
||||||
nextAbortController: new AbortController(),
|
const nextAbortController = ref(new AbortController());
|
||||||
|
|
||||||
|
const nav = computed(() => {
|
||||||
|
return decodeURIComponent(current.value);
|
||||||
|
});
|
||||||
|
|
||||||
|
const abortOngoingNext = () => {
|
||||||
|
nextAbortController.value.abort();
|
||||||
};
|
};
|
||||||
},
|
|
||||||
inject: ["$showError"],
|
const fillOptions = (reqData: any) => {
|
||||||
computed: {
|
|
||||||
...mapState(useAuthStore, ["user"]),
|
|
||||||
...mapState(useFileStore, ["req"]),
|
|
||||||
nav() {
|
|
||||||
return decodeURIComponent(this.current);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.fillOptions(this.req);
|
|
||||||
},
|
|
||||||
unmounted() {
|
|
||||||
this.abortOngoingNext();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
abortOngoingNext() {
|
|
||||||
this.nextAbortController.abort();
|
|
||||||
},
|
|
||||||
fillOptions(req) {
|
|
||||||
// Sets the current path and resets
|
// Sets the current path and resets
|
||||||
// the current items.
|
// the current items.
|
||||||
this.current = req.url;
|
current.value = reqData.url;
|
||||||
this.items = [];
|
items.value = [];
|
||||||
|
|
||||||
this.$emit("update:selected", this.current);
|
emit("update:selected", current.value);
|
||||||
|
|
||||||
// If the path isn't the root path,
|
// If the path isn't the root path,
|
||||||
// show a button to navigate to the previous
|
// show a button to navigate to the previous
|
||||||
// directory.
|
// directory.
|
||||||
if (req.url !== "/files/") {
|
if (reqData.url !== "/files/") {
|
||||||
this.items.push({
|
items.value.push({
|
||||||
name: "..",
|
name: "..",
|
||||||
url: url.removeLastDir(req.url) + "/",
|
url: url.removeLastDir(reqData.url) + "/",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this folder is empty, finish here.
|
// If this folder is empty, finish here.
|
||||||
if (req.items === null) return;
|
if (reqData.items === null) return;
|
||||||
|
|
||||||
// Otherwise we add every directory to the
|
// Otherwise we add every directory to the
|
||||||
// move options.
|
// move options.
|
||||||
for (const item of req.items) {
|
for (const item of reqData.items) {
|
||||||
if (!item.isDir) continue;
|
if (!item.isDir) continue;
|
||||||
if (this.exclude?.includes(item.url)) continue;
|
if (props.exclude?.includes(item.url)) continue;
|
||||||
|
|
||||||
this.items.push({
|
items.value.push({
|
||||||
name: item.name,
|
name: item.name,
|
||||||
url: item.url,
|
url: item.url,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
next: function (event) {
|
|
||||||
|
const next = (event: Event) => {
|
||||||
// Retrieves the URL of the directory the user
|
// Retrieves the URL of the directory the user
|
||||||
// just clicked in and fill the options with its
|
// just clicked in and fill the options with its
|
||||||
// content.
|
// content.
|
||||||
const uri = event.currentTarget.dataset.url;
|
const uri = (event.currentTarget as HTMLElement).dataset.url!;
|
||||||
this.abortOngoingNext();
|
abortOngoingNext();
|
||||||
this.nextAbortController = new AbortController();
|
nextAbortController.value = new AbortController();
|
||||||
files
|
files
|
||||||
.fetch(uri, this.nextAbortController.signal)
|
.fetch(uri, nextAbortController.value.signal)
|
||||||
.then(this.fillOptions)
|
.then(fillOptions)
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
if (e instanceof StatusError && e.is_canceled) {
|
if (e instanceof StatusError && e.is_canceled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.$showError(e);
|
$showError?.(e);
|
||||||
});
|
});
|
||||||
},
|
};
|
||||||
touchstart(event) {
|
|
||||||
const url = event.currentTarget.dataset.url;
|
const touchstart = (event: Event) => {
|
||||||
|
const urlValue = (event.currentTarget as HTMLElement).dataset.url!;
|
||||||
|
|
||||||
// In 300 milliseconds, we shall reset the count.
|
// In 300 milliseconds, we shall reset the count.
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.touches.count = 0;
|
touches.value.count = 0;
|
||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
// If the element the user is touching
|
// If the element the user is touching
|
||||||
// is different from the last one he touched,
|
// is different from the last one he touched,
|
||||||
// reset the count.
|
// reset the count.
|
||||||
if (this.touches.id !== url) {
|
if (touches.value.id !== urlValue) {
|
||||||
this.touches.id = url;
|
touches.value.id = urlValue;
|
||||||
this.touches.count = 1;
|
touches.value.count = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.touches.count++;
|
touches.value.count++;
|
||||||
|
|
||||||
// If there is more than one touch already,
|
// If there is more than one touch already,
|
||||||
// open the next screen.
|
// open the next screen.
|
||||||
if (this.touches.count > 1) {
|
if (touches.value.count > 1) {
|
||||||
this.next(event);
|
next(event);
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
itemClick: function (event) {
|
|
||||||
if (this.user.singleClick) this.next(event);
|
const itemClick = (event: Event) => {
|
||||||
else this.select(event);
|
if (user.value?.singleClick) next(event);
|
||||||
},
|
else select(event);
|
||||||
select: function (event) {
|
};
|
||||||
|
|
||||||
|
const select = (event: Event) => {
|
||||||
|
const urlValue = (event.currentTarget as HTMLElement).dataset.url!;
|
||||||
// If the element is already selected, unselect it.
|
// If the element is already selected, unselect it.
|
||||||
if (this.selected === event.currentTarget.dataset.url) {
|
if (selected.value === urlValue) {
|
||||||
this.selected = null;
|
selected.value = null;
|
||||||
this.$emit("update:selected", this.current);
|
emit("update:selected", current.value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise select the element.
|
// Otherwise select the element.
|
||||||
this.selected = event.currentTarget.dataset.url;
|
selected.value = urlValue;
|
||||||
this.$emit("update:selected", this.selected);
|
emit("update:selected", selected.value);
|
||||||
},
|
};
|
||||||
createDir: async function () {
|
|
||||||
this.$store.commit("showHover", {
|
const createDir = async () => {
|
||||||
|
showHover({
|
||||||
prompt: "newDir",
|
prompt: "newDir",
|
||||||
action: null,
|
action: undefined,
|
||||||
confirm: null,
|
confirm: undefined,
|
||||||
props: {
|
props: {
|
||||||
redirect: false,
|
redirect: false,
|
||||||
base: this.current === this.$route.path ? null : this.current,
|
base: current.value === route.path ? null : current.value,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (req.value) {
|
||||||
|
fillOptions(req.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
abortOngoingNext();
|
||||||
|
});
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
createDir,
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -34,14 +34,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { mapActions } from "pinia";
|
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
|
|
||||||
export default {
|
const { closeHovers } = useLayoutStore();
|
||||||
name: "help",
|
|
||||||
methods: {
|
|
||||||
...mapActions(useLayoutStore, ["closeHovers"]),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -29,10 +29,10 @@
|
|||||||
|
|
||||||
<template v-if="dir && selected.length === 0">
|
<template v-if="dir && selected.length === 0">
|
||||||
<p>
|
<p>
|
||||||
<strong>{{ $t("prompts.numberFiles") }}:</strong> {{ req.numFiles }}
|
<strong>{{ $t("prompts.numberFiles") }}:</strong> {{ req?.numFiles }}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<strong>{{ $t("prompts.numberDirs") }}:</strong> {{ req.numDirs }}
|
<strong>{{ $t("prompts.numberDirs") }}:</strong> {{ req?.numDirs }}
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -99,98 +99,100 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { mapActions, mapState } from "pinia";
|
import { computed, inject } from "vue";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
import { useFileStore } from "@/stores/file";
|
import { useFileStore } from "@/stores/file";
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
import { filesize } from "@/utils";
|
import { filesize } from "@/utils";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { files as api } from "@/api";
|
import { files as api } from "@/api";
|
||||||
|
|
||||||
export default {
|
const route = useRoute();
|
||||||
name: "info",
|
const $showError = inject<(error: unknown) => void>("$showError");
|
||||||
inject: ["$showError"],
|
|
||||||
computed: {
|
const fileStore = useFileStore();
|
||||||
...mapState(useFileStore, [
|
const layoutStore = useLayoutStore();
|
||||||
"req",
|
|
||||||
"selected",
|
const { req, selected, selectedCount, isListing } = storeToRefs(fileStore);
|
||||||
"selectedCount",
|
const { closeHovers } = layoutStore;
|
||||||
"isListing",
|
|
||||||
]),
|
const humanSize = computed(() => {
|
||||||
humanSize: function () {
|
if (selectedCount.value === 0 || !isListing.value) {
|
||||||
if (this.selectedCount === 0 || !this.isListing) {
|
return filesize(req.value?.size ?? 0);
|
||||||
return filesize(this.req.size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let sum = 0;
|
let sum = 0;
|
||||||
|
|
||||||
for (const selected of this.selected) {
|
for (const selectedIdx of selected.value) {
|
||||||
sum += this.req.items[selected].size;
|
sum += req.value?.items[selectedIdx]?.size ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return filesize(sum);
|
return filesize(sum);
|
||||||
},
|
});
|
||||||
humanTime: function () {
|
|
||||||
if (this.selectedCount === 0) {
|
const humanTime = computed(() => {
|
||||||
return dayjs(this.req.modified).fromNow();
|
if (selectedCount.value === 0) {
|
||||||
|
return dayjs(req.value?.modified).fromNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
return dayjs(this.req.items[this.selected[0]].modified).fromNow();
|
return dayjs(req.value?.items[selected.value[0]]?.modified).fromNow();
|
||||||
},
|
});
|
||||||
modTime: function () {
|
|
||||||
if (this.selectedCount === 0) {
|
const modTime = computed(() => {
|
||||||
return new Date(Date.parse(this.req.modified)).toLocaleString();
|
if (selectedCount.value === 0) {
|
||||||
|
return new Date(Date.parse(req.value?.modified ?? "")).toLocaleString();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Date(
|
return new Date(
|
||||||
Date.parse(this.req.items[this.selected[0]].modified)
|
Date.parse(req.value?.items[selected.value[0]]?.modified ?? "")
|
||||||
).toLocaleString();
|
).toLocaleString();
|
||||||
},
|
});
|
||||||
name: function () {
|
|
||||||
return this.selectedCount === 0
|
const name = computed(() => {
|
||||||
? this.req.name
|
return selectedCount.value === 0
|
||||||
: this.req.items[this.selected[0]].name;
|
? (req.value?.name ?? "")
|
||||||
},
|
: (req.value?.items[selected.value[0]]?.name ?? "");
|
||||||
dir: function () {
|
});
|
||||||
|
|
||||||
|
const dir = computed(() => {
|
||||||
return (
|
return (
|
||||||
this.selectedCount > 1 ||
|
selectedCount.value > 1 ||
|
||||||
(this.selectedCount === 0
|
(selectedCount.value === 0
|
||||||
? this.req.isDir
|
? (req.value?.isDir ?? false)
|
||||||
: this.req.items[this.selected[0]].isDir)
|
: (req.value?.items[selected.value[0]]?.isDir ?? false))
|
||||||
);
|
);
|
||||||
},
|
});
|
||||||
resolution: function () {
|
|
||||||
if (this.selectedCount === 1) {
|
const resolution = computed(() => {
|
||||||
const selectedItem = this.req.items[this.selected[0]];
|
if (selectedCount.value === 1) {
|
||||||
|
const selectedItem = req.value?.items[selected.value[0]];
|
||||||
if (selectedItem && selectedItem.type === "image") {
|
if (selectedItem && selectedItem.type === "image") {
|
||||||
return selectedItem.resolution;
|
return (selectedItem as any).resolution;
|
||||||
}
|
}
|
||||||
} else if (this.req && this.req.type === "image") {
|
} else if (req.value && req.value.type === "image") {
|
||||||
return this.req.resolution;
|
return (req.value as any).resolution;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
});
|
||||||
},
|
|
||||||
methods: {
|
const checksum = async (event: Event, algo: string) => {
|
||||||
...mapActions(useLayoutStore, ["closeHovers"]),
|
|
||||||
checksum: async function (event, algo) {
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
let link;
|
let link;
|
||||||
|
|
||||||
if (this.selectedCount) {
|
if (selectedCount.value) {
|
||||||
link = this.req.items[this.selected[0]].url;
|
link = req.value?.items[selected.value[0]]?.url ?? "";
|
||||||
} else {
|
} else {
|
||||||
link = this.$route.path;
|
link = route.path;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const hash = await api.checksum(link, algo);
|
const hash = await api.checksum(link, algo as any);
|
||||||
event.target.textContent = hash;
|
(event.target as HTMLElement).textContent = hash;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.$showError(e);
|
$showError?.(e);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<file-list
|
<file-list
|
||||||
ref="fileList"
|
ref="fileList"
|
||||||
@update:selected="(val) => (dest = val)"
|
@update:selected="(val: string) => (dest = val)"
|
||||||
:exclude="excludedFolders"
|
:exclude="excludedFolders"
|
||||||
tabindex="1"
|
tabindex="1"
|
||||||
/>
|
/>
|
||||||
@@ -17,10 +17,10 @@
|
|||||||
class="card-action"
|
class="card-action"
|
||||||
style="display: flex; align-items: center; justify-content: space-between"
|
style="display: flex; align-items: center; justify-content: space-between"
|
||||||
>
|
>
|
||||||
<template v-if="user.perm.create">
|
<template v-if="user?.perm.create">
|
||||||
<button
|
<button
|
||||||
class="button button--flat"
|
class="button button--flat"
|
||||||
@click="$refs.fileList.createDir()"
|
@click="fileList?.createDir()"
|
||||||
:aria-label="$t('sidebar.newFolder')"
|
:aria-label="$t('sidebar.newFolder')"
|
||||||
:title="$t('sidebar.newFolder')"
|
:title="$t('sidebar.newFolder')"
|
||||||
style="justify-self: left"
|
style="justify-self: left"
|
||||||
@@ -54,8 +54,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { mapActions, mapState, mapWritableState } from "pinia";
|
import { ref, computed, inject } from "vue";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
import { useFileStore } from "@/stores/file";
|
import { useFileStore } from "@/stores/file";
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
import { useAuthStore } from "@/stores/auth";
|
import { useAuthStore } from "@/stores/auth";
|
||||||
@@ -65,71 +67,69 @@ import buttons from "@/utils/buttons";
|
|||||||
import * as upload from "@/utils/upload";
|
import * as upload from "@/utils/upload";
|
||||||
import { removePrefix } from "@/api/utils";
|
import { removePrefix } from "@/api/utils";
|
||||||
|
|
||||||
export default {
|
const router = useRouter();
|
||||||
name: "move",
|
const $showError = inject<(error: unknown) => void>("$showError");
|
||||||
components: { FileList },
|
|
||||||
data: function () {
|
|
||||||
return {
|
|
||||||
current: window.location.pathname,
|
|
||||||
dest: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
inject: ["$showError"],
|
|
||||||
computed: {
|
|
||||||
...mapState(useFileStore, ["req", "selected"]),
|
|
||||||
...mapState(useAuthStore, ["user"]),
|
|
||||||
...mapWritableState(useFileStore, ["preselect"]),
|
|
||||||
excludedFolders() {
|
|
||||||
return this.selected
|
|
||||||
.filter((idx) => this.req.items[idx].isDir)
|
|
||||||
.map((idx) => this.req.items[idx].url);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions(useLayoutStore, ["showHover", "closeHovers"]),
|
|
||||||
move: async function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
const items = [];
|
|
||||||
|
|
||||||
for (const item of this.selected) {
|
const fileStore = useFileStore();
|
||||||
|
const layoutStore = useLayoutStore();
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
|
||||||
|
const { req, selected } = storeToRefs(fileStore);
|
||||||
|
const { user } = storeToRefs(authStore);
|
||||||
|
const { showHover, closeHovers } = layoutStore;
|
||||||
|
|
||||||
|
const fileList = ref<InstanceType<typeof FileList> | null>(null);
|
||||||
|
const dest = ref<string | null>(null);
|
||||||
|
|
||||||
|
const excludedFolders = computed(() => {
|
||||||
|
return selected.value
|
||||||
|
.filter((idx) => req.value!.items[idx].isDir)
|
||||||
|
.map((idx) => req.value!.items[idx].url);
|
||||||
|
});
|
||||||
|
|
||||||
|
const move = async (event: Event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
const items: Array<{ from: string; to: string; name: string }> = [];
|
||||||
|
|
||||||
|
for (const item of selected.value) {
|
||||||
items.push({
|
items.push({
|
||||||
from: this.req.items[item].url,
|
from: req.value!.items[item].url,
|
||||||
to: this.dest + encodeURIComponent(this.req.items[item].name),
|
to: dest.value! + encodeURIComponent(req.value!.items[item].name),
|
||||||
name: this.req.items[item].name,
|
name: req.value!.items[item].name,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const action = async (overwrite, rename) => {
|
const action = async (overwrite: boolean, rename: boolean) => {
|
||||||
buttons.loading("move");
|
buttons.loading("move");
|
||||||
|
|
||||||
await api
|
await api
|
||||||
.move(items, overwrite, rename)
|
.move(items, overwrite, rename)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
buttons.success("move");
|
buttons.success("move");
|
||||||
this.preselect = removePrefix(items[0].to);
|
fileStore.preselect = removePrefix(items[0].to);
|
||||||
this.$router.push({ path: this.dest });
|
router.push({ path: dest.value! });
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
buttons.done("move");
|
buttons.done("move");
|
||||||
this.$showError(e);
|
$showError?.(e);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const dstItems = (await api.fetch(this.dest)).items;
|
const dstItems = (await api.fetch(dest.value!)).items;
|
||||||
const conflict = upload.checkConflict(items, dstItems);
|
const conflict = upload.checkConflict(items as any, dstItems);
|
||||||
|
|
||||||
let overwrite = false;
|
let overwrite = false;
|
||||||
let rename = false;
|
let rename = false;
|
||||||
|
|
||||||
if (conflict) {
|
if (conflict) {
|
||||||
this.showHover({
|
showHover({
|
||||||
prompt: "replace-rename",
|
prompt: "replace-rename",
|
||||||
confirm: (event, option) => {
|
confirm: (event: Event, option: string) => {
|
||||||
overwrite = option == "overwrite";
|
overwrite = option == "overwrite";
|
||||||
rename = option == "rename";
|
rename = option == "rename";
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.closeHovers();
|
closeHovers();
|
||||||
action(overwrite, rename);
|
action(overwrite, rename);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -138,7 +138,5 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
action(overwrite, rename);
|
action(overwrite, rename);
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
v-model.trim="name"
|
v-model.trim="name"
|
||||||
tabindex="1"
|
tabindex="1"
|
||||||
/>
|
/>
|
||||||
|
<CreateFilePath :name="name" :is-dir="true" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-action">
|
<div class="card-action">
|
||||||
@@ -48,6 +49,7 @@ import { files as api } from "@/api";
|
|||||||
import url from "@/utils/url";
|
import url from "@/utils/url";
|
||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
import CreateFilePath from "@/components/prompts/CreateFilePath.vue";
|
||||||
|
|
||||||
const $showError = inject<IToastError>("$showError")!;
|
const $showError = inject<IToastError>("$showError")!;
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
@keyup.enter="submit"
|
@keyup.enter="submit"
|
||||||
v-model.trim="name"
|
v-model.trim="name"
|
||||||
/>
|
/>
|
||||||
|
<CreateFilePath :name="name" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card-action">
|
<div class="card-action">
|
||||||
@@ -42,6 +43,7 @@ import { useI18n } from "vue-i18n";
|
|||||||
import { useRoute, useRouter } from "vue-router";
|
import { useRoute, useRouter } from "vue-router";
|
||||||
import { useFileStore } from "@/stores/file";
|
import { useFileStore } from "@/stores/file";
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
|
import CreateFilePath from "@/components/prompts/CreateFilePath.vue";
|
||||||
|
|
||||||
import { files as api } from "@/api";
|
import { files as api } from "@/api";
|
||||||
import url from "@/utils/url";
|
import url from "@/utils/url";
|
||||||
|
|||||||
@@ -40,80 +40,74 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { mapActions, mapState, mapWritableState } from "pinia";
|
import { ref, onMounted, inject } from "vue";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
import { useFileStore } from "@/stores/file";
|
import { useFileStore } from "@/stores/file";
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
import url from "@/utils/url";
|
import url from "@/utils/url";
|
||||||
import { files as api } from "@/api";
|
import { files as api } from "@/api";
|
||||||
import { removePrefix } from "@/api/utils";
|
import { removePrefix } from "@/api/utils";
|
||||||
|
|
||||||
export default {
|
const router = useRouter();
|
||||||
name: "rename",
|
const $showError = inject<(error: unknown) => void>("$showError");
|
||||||
data: function () {
|
|
||||||
return {
|
const fileStore = useFileStore();
|
||||||
name: "",
|
const layoutStore = useLayoutStore();
|
||||||
};
|
|
||||||
},
|
const { req, selected, selectedCount, isListing } = storeToRefs(fileStore);
|
||||||
created() {
|
const { closeHovers } = layoutStore;
|
||||||
this.name = this.oldName();
|
|
||||||
},
|
const name = ref("");
|
||||||
inject: ["$showError"],
|
|
||||||
computed: {
|
const oldName = (): string => {
|
||||||
...mapState(useFileStore, [
|
if (!isListing.value) {
|
||||||
"req",
|
return req.value?.name ?? "";
|
||||||
"selected",
|
|
||||||
"selectedCount",
|
|
||||||
"isListing",
|
|
||||||
]),
|
|
||||||
...mapWritableState(useFileStore, ["reload", "preselect"]),
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions(useLayoutStore, ["closeHovers"]),
|
|
||||||
cancel: function () {
|
|
||||||
this.closeHovers();
|
|
||||||
},
|
|
||||||
oldName: function () {
|
|
||||||
if (!this.isListing) {
|
|
||||||
return this.req.name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.selectedCount === 0 || this.selectedCount > 1) {
|
if (selectedCount.value === 0 || selectedCount.value > 1) {
|
||||||
// This shouldn't happen.
|
// This shouldn't happen.
|
||||||
return;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.req.items[this.selected[0]].name;
|
return req.value?.items[selected.value[0]].name ?? "";
|
||||||
},
|
};
|
||||||
submit: async function () {
|
|
||||||
|
onMounted(() => {
|
||||||
|
name.value = oldName();
|
||||||
|
});
|
||||||
|
|
||||||
|
const submit = async () => {
|
||||||
let oldLink = "";
|
let oldLink = "";
|
||||||
let newLink = "";
|
let newLink = "";
|
||||||
|
|
||||||
if (!this.isListing) {
|
if (!req.value) {
|
||||||
oldLink = this.req.url;
|
|
||||||
} else {
|
|
||||||
oldLink = this.req.items[this.selected[0]].url;
|
|
||||||
}
|
|
||||||
|
|
||||||
newLink =
|
|
||||||
url.removeLastDir(oldLink) + "/" + encodeURIComponent(this.name);
|
|
||||||
|
|
||||||
try {
|
|
||||||
await api.move([{ from: oldLink, to: newLink }]);
|
|
||||||
if (!this.isListing) {
|
|
||||||
this.$router.push({ path: newLink });
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.preselect = removePrefix(newLink);
|
if (!isListing.value) {
|
||||||
|
oldLink = req.value.url;
|
||||||
this.reload = true;
|
} else {
|
||||||
} catch (e) {
|
oldLink = req.value.items[selected.value[0]].url;
|
||||||
this.$showError(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.closeHovers();
|
newLink = url.removeLastDir(oldLink) + "/" + encodeURIComponent(name.value);
|
||||||
},
|
|
||||||
},
|
try {
|
||||||
|
await api.move([{ from: oldLink, to: newLink }]);
|
||||||
|
if (!isListing.value) {
|
||||||
|
router.push({ path: newLink });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fileStore.preselect = removePrefix(newLink);
|
||||||
|
|
||||||
|
fileStore.reload = true;
|
||||||
|
} catch (e) {
|
||||||
|
$showError?.(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
closeHovers();
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="button button--flat button--blue"
|
class="button button--flat button--blue"
|
||||||
@click="currentPrompt.action"
|
@click="currentPrompt?.action"
|
||||||
:aria-label="$t('buttons.continue')"
|
:aria-label="$t('buttons.continue')"
|
||||||
:title="$t('buttons.continue')"
|
:title="$t('buttons.continue')"
|
||||||
tabindex="2"
|
tabindex="2"
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<button
|
<button
|
||||||
id="focus-prompt"
|
id="focus-prompt"
|
||||||
class="button button--flat button--red"
|
class="button button--flat button--red"
|
||||||
@click="currentPrompt.confirm"
|
@click="currentPrompt?.confirm"
|
||||||
:aria-label="$t('buttons.replace')"
|
:aria-label="$t('buttons.replace')"
|
||||||
:title="$t('buttons.replace')"
|
:title="$t('buttons.replace')"
|
||||||
tabindex="1"
|
tabindex="1"
|
||||||
@@ -41,17 +41,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { mapActions, mapState } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
|
|
||||||
export default {
|
const layoutStore = useLayoutStore();
|
||||||
name: "replace",
|
const { currentPrompt } = storeToRefs(layoutStore);
|
||||||
computed: {
|
const { closeHovers } = layoutStore;
|
||||||
...mapState(useLayoutStore, ["currentPrompt"]),
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions(useLayoutStore, ["closeHovers"]),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="button button--flat button--blue"
|
class="button button--flat button--blue"
|
||||||
@click="(event) => currentPrompt.confirm(event, 'rename')"
|
@click="(event) => currentPrompt?.confirm(event, 'rename')"
|
||||||
:aria-label="$t('buttons.rename')"
|
:aria-label="$t('buttons.rename')"
|
||||||
:title="$t('buttons.rename')"
|
:title="$t('buttons.rename')"
|
||||||
tabindex="2"
|
tabindex="2"
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<button
|
<button
|
||||||
id="focus-prompt"
|
id="focus-prompt"
|
||||||
class="button button--flat button--red"
|
class="button button--flat button--red"
|
||||||
@click="(event) => currentPrompt.confirm(event, 'overwrite')"
|
@click="(event) => currentPrompt?.confirm(event, 'overwrite')"
|
||||||
:aria-label="$t('buttons.replace')"
|
:aria-label="$t('buttons.replace')"
|
||||||
:title="$t('buttons.replace')"
|
:title="$t('buttons.replace')"
|
||||||
tabindex="1"
|
tabindex="1"
|
||||||
@@ -41,17 +41,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { mapActions, mapState } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
|
|
||||||
export default {
|
const layoutStore = useLayoutStore();
|
||||||
name: "replace-rename",
|
const { currentPrompt } = storeToRefs(layoutStore);
|
||||||
computed: {
|
const { closeHovers } = layoutStore;
|
||||||
...mapState(useLayoutStore, ["currentPrompt"]),
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions(useLayoutStore, ["closeHovers"]),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -129,138 +129,146 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { mapActions, mapState } from "pinia";
|
import { ref, computed, inject, onBeforeMount } from "vue";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
import { useFileStore } from "@/stores/file";
|
import { useFileStore } from "@/stores/file";
|
||||||
import { share as api } from "@/api";
|
import { share as api } from "@/api";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
import { copy } from "@/utils/clipboard";
|
import { copy } from "@/utils/clipboard";
|
||||||
|
|
||||||
export default {
|
const route = useRoute();
|
||||||
name: "share",
|
const { t } = useI18n();
|
||||||
data: function () {
|
const $showError = inject<(error: unknown) => void>("$showError");
|
||||||
return {
|
const $showSuccess = inject<(message: string) => void>("$showSuccess");
|
||||||
time: 0,
|
|
||||||
unit: "hours",
|
const fileStore = useFileStore();
|
||||||
links: [],
|
const layoutStore = useLayoutStore();
|
||||||
clip: null,
|
|
||||||
password: "",
|
const { req, selected, selectedCount, isListing } = storeToRefs(fileStore);
|
||||||
listing: true,
|
const { closeHovers } = layoutStore;
|
||||||
};
|
|
||||||
},
|
const time = ref(0);
|
||||||
inject: ["$showError", "$showSuccess"],
|
const unit = ref("hours");
|
||||||
computed: {
|
const links = ref<any[]>([]);
|
||||||
...mapState(useFileStore, [
|
const password = ref("");
|
||||||
"req",
|
const listing = ref(true);
|
||||||
"selected",
|
|
||||||
"selectedCount",
|
const url = computed(() => {
|
||||||
"isListing",
|
if (!isListing.value) {
|
||||||
]),
|
return route.path;
|
||||||
url() {
|
|
||||||
if (!this.isListing) {
|
|
||||||
return this.$route.path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.selectedCount === 0 || this.selectedCount > 1) {
|
if (selectedCount.value === 0 || selectedCount.value > 1) {
|
||||||
// This shouldn't happen.
|
// This shouldn't happen.
|
||||||
return;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.req.items[this.selected[0]].url;
|
return req.value?.items[selected.value[0]].url ?? "";
|
||||||
},
|
});
|
||||||
},
|
|
||||||
async beforeMount() {
|
|
||||||
try {
|
|
||||||
const links = await api.get(this.url);
|
|
||||||
this.links = links;
|
|
||||||
this.sort();
|
|
||||||
|
|
||||||
if (this.links.length == 0) {
|
const copyToClipboard = (text: string) => {
|
||||||
this.listing = false;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
this.$showError(e);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
...mapActions(useLayoutStore, ["closeHovers"]),
|
|
||||||
copyToClipboard: function (text) {
|
|
||||||
copy({ text }).then(
|
copy({ text }).then(
|
||||||
() => {
|
() => {
|
||||||
// clipboard successfully set
|
// clipboard successfully set
|
||||||
this.$showSuccess(this.$t("success.linkCopied"));
|
$showSuccess?.(t("success.linkCopied"));
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
// clipboard write failed
|
// clipboard write failed
|
||||||
copy({ text }, { permission: true }).then(
|
copy({ text }, { permission: true }).then(
|
||||||
() => {
|
() => {
|
||||||
// clipboard successfully set
|
// clipboard successfully set
|
||||||
this.$showSuccess(this.$t("success.linkCopied"));
|
$showSuccess?.(t("success.linkCopied"));
|
||||||
},
|
},
|
||||||
(e) => {
|
(e) => {
|
||||||
// clipboard write failed
|
// clipboard write failed
|
||||||
this.$showError(e);
|
$showError?.(e);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
};
|
||||||
submit: async function () {
|
|
||||||
|
const submit = async () => {
|
||||||
try {
|
try {
|
||||||
let res = null;
|
let res = null;
|
||||||
|
|
||||||
if (!this.time) {
|
if (!time.value) {
|
||||||
res = await api.create(this.url, this.password);
|
res = await api.create(url.value, password.value);
|
||||||
} else {
|
} else {
|
||||||
res = await api.create(this.url, this.password, this.time, this.unit);
|
res = await api.create(
|
||||||
|
url.value,
|
||||||
|
password.value,
|
||||||
|
String(time.value),
|
||||||
|
unit.value
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.links.push(res);
|
links.value.push(res);
|
||||||
this.sort();
|
sort();
|
||||||
|
|
||||||
this.time = 0;
|
time.value = 0;
|
||||||
this.unit = "hours";
|
unit.value = "hours";
|
||||||
this.password = "";
|
password.value = "";
|
||||||
|
|
||||||
this.listing = true;
|
listing.value = true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.$showError(e);
|
$showError?.(e);
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
deleteLink: async function (event, link) {
|
|
||||||
|
const deleteLink = async (event: Event, link: any) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
try {
|
try {
|
||||||
await api.remove(link.hash);
|
await api.remove(link.hash);
|
||||||
this.links = this.links.filter((item) => item.hash !== link.hash);
|
links.value = links.value.filter((item) => item.hash !== link.hash);
|
||||||
|
|
||||||
if (this.links.length == 0) {
|
if (links.value.length == 0) {
|
||||||
this.listing = false;
|
listing.value = false;
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.$showError(e);
|
$showError?.(e);
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
humanTime(time) {
|
|
||||||
|
const humanTime = (time: number) => {
|
||||||
return dayjs(time * 1000).fromNow();
|
return dayjs(time * 1000).fromNow();
|
||||||
},
|
};
|
||||||
buildLink(share) {
|
|
||||||
|
const buildLink = (share: any) => {
|
||||||
return api.getShareURL(share);
|
return api.getShareURL(share);
|
||||||
},
|
};
|
||||||
sort() {
|
|
||||||
this.links = this.links.sort((a, b) => {
|
const sort = () => {
|
||||||
|
links.value = links.value.sort((a, b) => {
|
||||||
if (a.expire === 0) return -1;
|
if (a.expire === 0) return -1;
|
||||||
if (b.expire === 0) return 1;
|
if (b.expire === 0) return 1;
|
||||||
return new Date(a.expire) - new Date(b.expire);
|
return new Date(a.expire).getTime() - new Date(b.expire).getTime();
|
||||||
});
|
});
|
||||||
},
|
};
|
||||||
switchListing() {
|
|
||||||
if (this.links.length == 0 && !this.listing) {
|
const switchListing = () => {
|
||||||
this.closeHovers();
|
if (links.value.length == 0 && !listing.value) {
|
||||||
|
closeHovers();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.listing = !this.listing;
|
listing.value = !listing.value;
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onBeforeMount(async () => {
|
||||||
|
try {
|
||||||
|
const fetchedLinks = await api.get(url.value);
|
||||||
|
links.value = Array.isArray(fetchedLinks) ? fetchedLinks : [fetchedLinks];
|
||||||
|
sort();
|
||||||
|
|
||||||
|
if (links.value.length == 0) {
|
||||||
|
listing.value = false;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
$showError?.(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -27,20 +27,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { mapActions, mapState } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
import { useLayoutStore } from "@/stores/layout";
|
import { useLayoutStore } from "@/stores/layout";
|
||||||
|
|
||||||
export default {
|
const layoutStore = useLayoutStore();
|
||||||
name: "share-delete",
|
const { currentPrompt } = storeToRefs(layoutStore);
|
||||||
computed: {
|
const { closeHovers } = layoutStore;
|
||||||
...mapState(useLayoutStore, ["currentPrompt"]),
|
|
||||||
},
|
const submit = () => {
|
||||||
methods: {
|
currentPrompt.value?.confirm();
|
||||||
...mapActions(useLayoutStore, ["closeHovers"]),
|
|
||||||
submit: function () {
|
|
||||||
this.currentPrompt?.confirm();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
}}
|
}}
|
||||||
</h2>
|
</h2>
|
||||||
<div class="upload-info">
|
<div class="upload-info">
|
||||||
<div class="upload-speed">{{ speedMbytes }}/s</div>
|
<div class="upload-speed">{{ speedText }}/s</div>
|
||||||
<div class="upload-eta">{{ formattedETA }} remaining</div>
|
<div class="upload-eta">{{ formattedETA }} remaining</div>
|
||||||
<div class="upload-percentage">{{ sentPercent }}% Completed</div>
|
<div class="upload-percentage">{{ sentPercent }}% Completed</div>
|
||||||
<div class="upload-fraction">
|
<div class="upload-fraction">
|
||||||
@@ -88,6 +88,7 @@ const uploadStore = useUploadStore();
|
|||||||
const { sentBytes, totalBytes } = storeToRefs(uploadStore);
|
const { sentBytes, totalBytes } = storeToRefs(uploadStore);
|
||||||
|
|
||||||
const byteToMbyte = partial({ exponent: 2 });
|
const byteToMbyte = partial({ exponent: 2 });
|
||||||
|
const byteToKbyte = partial({ exponent: 1 });
|
||||||
|
|
||||||
const sentPercent = computed(() =>
|
const sentPercent = computed(() =>
|
||||||
((uploadStore.sentBytes / uploadStore.totalBytes) * 100).toFixed(2)
|
((uploadStore.sentBytes / uploadStore.totalBytes) * 100).toFixed(2)
|
||||||
@@ -95,11 +96,33 @@ const sentPercent = computed(() =>
|
|||||||
|
|
||||||
const sentMbytes = computed(() => byteToMbyte(uploadStore.sentBytes));
|
const sentMbytes = computed(() => byteToMbyte(uploadStore.sentBytes));
|
||||||
const totalMbytes = computed(() => byteToMbyte(uploadStore.totalBytes));
|
const totalMbytes = computed(() => byteToMbyte(uploadStore.totalBytes));
|
||||||
const speedMbytes = computed(() => byteToMbyte(speed.value));
|
const speedText = computed(() => {
|
||||||
|
const bytes = speed.value;
|
||||||
|
|
||||||
|
if (bytes < 1024 * 1024) {
|
||||||
|
const kb = parseFloat(byteToKbyte(bytes));
|
||||||
|
return `${kb.toFixed(2)} KB`;
|
||||||
|
} else {
|
||||||
|
const mb = parseFloat(byteToMbyte(bytes));
|
||||||
|
return `${mb.toFixed(2)} MB`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let lastSpeedUpdate: number = 0;
|
let lastSpeedUpdate: number = 0;
|
||||||
let recentSpeeds: number[] = [];
|
let recentSpeeds: number[] = [];
|
||||||
|
|
||||||
|
let lastThrottleTime = 0;
|
||||||
|
|
||||||
|
const throttledCalculateSpeed = (sentBytes: number, oldSentBytes: number) => {
|
||||||
|
const now = Date.now();
|
||||||
|
if (now - lastThrottleTime < 100) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastThrottleTime = now;
|
||||||
|
calculateSpeed(sentBytes, oldSentBytes);
|
||||||
|
};
|
||||||
|
|
||||||
const calculateSpeed = (sentBytes: number, oldSentBytes: number) => {
|
const calculateSpeed = (sentBytes: number, oldSentBytes: number) => {
|
||||||
// Reset the state when the uploads batch is complete
|
// Reset the state when the uploads batch is complete
|
||||||
if (sentBytes === 0) {
|
if (sentBytes === 0) {
|
||||||
@@ -149,7 +172,7 @@ const calculateEta = () => {
|
|||||||
eta.value = remainingSize / speedBytesPerSecond;
|
eta.value = remainingSize / speedBytesPerSecond;
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(sentBytes, calculateSpeed);
|
watch(sentBytes, throttledCalculateSpeed);
|
||||||
|
|
||||||
watch(totalBytes, (totalBytes, oldTotalBytes) => {
|
watch(totalBytes, (totalBytes, oldTotalBytes) => {
|
||||||
if (oldTotalBytes !== 0) {
|
if (oldTotalBytes !== 0) {
|
||||||
|
|||||||
28
frontend/src/components/settings/AceEditorTheme.vue
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<template>
|
||||||
|
<select
|
||||||
|
name="selectAceEditorTheme"
|
||||||
|
v-on:change="change"
|
||||||
|
:value="aceEditorTheme"
|
||||||
|
>
|
||||||
|
<option v-for="theme in themes" :value="theme.theme" :key="theme.theme">
|
||||||
|
{{ theme.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { type SelectHTMLAttributes } from "vue";
|
||||||
|
import { themes } from "ace-builds/src-noconflict/ext-themelist";
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
aceEditorTheme: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "update:aceEditorTheme", val: string | null): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const change = (event: Event) => {
|
||||||
|
emit("update:aceEditorTheme", (event.target as SelectHTMLAttributes)?.value);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -8,23 +8,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
export default {
|
import { computed } from "vue";
|
||||||
name: "permissions",
|
|
||||||
props: ["commands"],
|
const props = defineProps<{
|
||||||
computed: {
|
commands: string[];
|
||||||
raw: {
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
"update:commands": [commands: string[]];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const raw = computed({
|
||||||
get() {
|
get() {
|
||||||
return this.commands.join(" ");
|
return props.commands.join(" ");
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value: string) {
|
||||||
if (value !== "") {
|
if (value !== "") {
|
||||||
this.$emit("update:commands", value.split(" "));
|
emit("update:commands", value.split(" "));
|
||||||
} else {
|
} else {
|
||||||
this.$emit("update:commands", []);
|
emit("update:commands", []);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -6,16 +6,20 @@
|
|||||||
</select>
|
</select>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { markRaw } from "vue";
|
import { markRaw } from "vue";
|
||||||
|
|
||||||
export default {
|
defineProps<{
|
||||||
name: "languages",
|
locale: string;
|
||||||
props: ["locale"],
|
}>();
|
||||||
data() {
|
|
||||||
const dataObj = {};
|
const emit = defineEmits<{
|
||||||
const locales = {
|
"update:locale": [locale: string];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const locales = markRaw({
|
||||||
he: "עברית",
|
he: "עברית",
|
||||||
|
hr: "Hrvatski",
|
||||||
hu: "Magyar",
|
hu: "Magyar",
|
||||||
ar: "العربية",
|
ar: "العربية",
|
||||||
ca: "Català",
|
ca: "Català",
|
||||||
@@ -43,23 +47,9 @@ export default {
|
|||||||
vi: "Tiếng Việt",
|
vi: "Tiếng Việt",
|
||||||
"zh-cn": "中文 (简体)",
|
"zh-cn": "中文 (简体)",
|
||||||
"zh-tw": "中文 (繁體)",
|
"zh-tw": "中文 (繁體)",
|
||||||
};
|
|
||||||
|
|
||||||
// Vue3 reactivity breaks with this configuration
|
|
||||||
// so we need to use markRaw as a workaround
|
|
||||||
// https://github.com/vuejs/core/issues/3024
|
|
||||||
Object.defineProperty(dataObj, "locales", {
|
|
||||||
value: markRaw(locales),
|
|
||||||
configurable: false,
|
|
||||||
writable: false,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return dataObj;
|
const change = (event: Event) => {
|
||||||
},
|
emit("update:locale", (event.target as HTMLSelectElement).value);
|
||||||
methods: {
|
|
||||||
change(event) {
|
|
||||||
this.$emit("update:locale", event.target.value);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -39,27 +39,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
|
import { computed } from "vue";
|
||||||
import { enableExec } from "@/utils/constants";
|
import { enableExec } from "@/utils/constants";
|
||||||
export default {
|
|
||||||
name: "permissions",
|
const props = defineProps<{
|
||||||
props: ["perm"],
|
perm: UserPermissions;
|
||||||
computed: {
|
}>();
|
||||||
admin: {
|
|
||||||
|
const admin = computed({
|
||||||
get() {
|
get() {
|
||||||
return this.perm.admin;
|
return props.perm.admin;
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value: boolean) {
|
||||||
if (value) {
|
if (value) {
|
||||||
for (const key in this.perm) {
|
for (const key in props.perm) {
|
||||||
this.perm[key] = true;
|
props.perm[key as keyof UserPermissions] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.perm.admin = value;
|
props.perm.admin = value;
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
isExecEnabled: () => enableExec,
|
|
||||||
},
|
const isExecEnabled = enableExec;
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -32,22 +32,36 @@
|
|||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
export default {
|
interface Rule {
|
||||||
name: "rules-textarea",
|
allow: boolean;
|
||||||
props: ["rules"],
|
path: string;
|
||||||
methods: {
|
regex: boolean;
|
||||||
remove(event, index) {
|
regexp: {
|
||||||
|
raw: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
rules: Rule[];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
"update:rules": [rules: Rule[]];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const remove = (event: Event, index: number) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const rules = [...this.rules];
|
const rules = [...props.rules];
|
||||||
rules.splice(index, 1);
|
rules.splice(index, 1);
|
||||||
this.$emit("update:rules", [...rules]);
|
emit("update:rules", [...rules]);
|
||||||
},
|
};
|
||||||
create(event) {
|
|
||||||
|
const create = (event: Event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
this.$emit("update:rules", [
|
emit("update:rules", [
|
||||||
...this.rules,
|
...props.rules,
|
||||||
{
|
{
|
||||||
allow: true,
|
allow: true,
|
||||||
path: "",
|
path: "",
|
||||||
@@ -57,7 +71,5 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -80,12 +80,20 @@ const { t } = useI18n();
|
|||||||
const createUserDirData = ref<boolean | null>(null);
|
const createUserDirData = ref<boolean | null>(null);
|
||||||
const originalUserScope = ref<string | null>(null);
|
const originalUserScope = ref<string | null>(null);
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<
|
||||||
|
| {
|
||||||
user: IUserForm;
|
user: IUserForm;
|
||||||
isNew: boolean;
|
isNew: boolean;
|
||||||
isDefault: boolean;
|
isDefault: false;
|
||||||
createUserDir?: boolean;
|
createUserDir?: boolean;
|
||||||
}>();
|
}
|
||||||
|
| {
|
||||||
|
user: SettingsDefaults;
|
||||||
|
isNew: boolean;
|
||||||
|
isDefault: true;
|
||||||
|
createUserDir?: boolean;
|
||||||
|
}
|
||||||
|
>();
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (props.user.scope) {
|
if (props.user.scope) {
|
||||||
@@ -108,6 +116,7 @@ watch(
|
|||||||
() => props.user,
|
() => props.user,
|
||||||
() => {
|
() => {
|
||||||
if (!props.user?.perm?.admin) return;
|
if (!props.user?.perm?.admin) return;
|
||||||
|
if (props.isDefault) return;
|
||||||
props.user.lockPassword = false;
|
props.user.lockPassword = false;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -63,8 +63,8 @@
|
|||||||
local("Roboto"),
|
local("Roboto"),
|
||||||
local("Roboto-Regular"),
|
local("Roboto-Regular"),
|
||||||
url(../assets/fonts/roboto/normal-latin-ext.woff2) format("woff2");
|
url(../assets/fonts/roboto/normal-latin-ext.woff2) format("woff2");
|
||||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF,
|
unicode-range:
|
||||||
U+2C60-2C7F, U+A720-A7FF;
|
U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
@@ -75,8 +75,9 @@
|
|||||||
local("Roboto"),
|
local("Roboto"),
|
||||||
local("Roboto-Regular"),
|
local("Roboto-Regular"),
|
||||||
url(../assets/fonts/roboto/normal-latin.woff2) format("woff2");
|
url(../assets/fonts/roboto/normal-latin.woff2) format("woff2");
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC,
|
unicode-range:
|
||||||
U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F,
|
||||||
|
U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
@@ -142,8 +143,8 @@
|
|||||||
local("Roboto Medium"),
|
local("Roboto Medium"),
|
||||||
local("Roboto-Medium"),
|
local("Roboto-Medium"),
|
||||||
url(../assets/fonts/roboto/medium-latin-ext.woff2) format("woff2");
|
url(../assets/fonts/roboto/medium-latin-ext.woff2) format("woff2");
|
||||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF,
|
unicode-range:
|
||||||
U+2C60-2C7F, U+A720-A7FF;
|
U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
@@ -154,8 +155,9 @@
|
|||||||
local("Roboto Medium"),
|
local("Roboto Medium"),
|
||||||
local("Roboto-Medium"),
|
local("Roboto-Medium"),
|
||||||
url(../assets/fonts/roboto/medium-latin.woff2) format("woff2");
|
url(../assets/fonts/roboto/medium-latin.woff2) format("woff2");
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC,
|
unicode-range:
|
||||||
U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F,
|
||||||
|
U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
@@ -221,8 +223,8 @@
|
|||||||
local("Roboto Bold"),
|
local("Roboto Bold"),
|
||||||
local("Roboto-Bold"),
|
local("Roboto-Bold"),
|
||||||
url(../assets/fonts/roboto/bold-latin-ext.woff2) format("woff2");
|
url(../assets/fonts/roboto/bold-latin-ext.woff2) format("woff2");
|
||||||
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF,
|
unicode-range:
|
||||||
U+2C60-2C7F, U+A720-A7FF;
|
U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
@@ -233,8 +235,9 @@
|
|||||||
local("Roboto Bold"),
|
local("Roboto Bold"),
|
||||||
local("Roboto-Bold"),
|
local("Roboto-Bold"),
|
||||||
url(../assets/fonts/roboto/bold-latin.woff2) format("woff2");
|
url(../assets/fonts/roboto/bold-latin.woff2) format("woff2");
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC,
|
unicode-range:
|
||||||
U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F,
|
||||||
|
U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.material-icons {
|
.material-icons {
|
||||||
|
|||||||
@@ -45,6 +45,15 @@
|
|||||||
animation: 0.2s opac forwards;
|
animation: 0.2s opac forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#login .logout-message {
|
||||||
|
background: var(--icon-orange);
|
||||||
|
color: #fff;
|
||||||
|
padding: 0.5em;
|
||||||
|
text-align: center;
|
||||||
|
animation: 0.2s opac forwards;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes opac {
|
@keyframes opac {
|
||||||
0% {
|
0% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
.md_preview {
|
.md_preview {
|
||||||
overflow-y: auto;
|
|
||||||
max-height: 80vh;
|
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border: 1px solid #000;
|
border: 1px solid #000;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
@@ -9,5 +7,5 @@
|
|||||||
|
|
||||||
#preview-container {
|
#preview-container {
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
max-height: 80vh; /* Match the max-height of md_preview for scrolling */
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "تحديث",
|
"update": "تحديث",
|
||||||
"upload": "رفع",
|
"upload": "رفع",
|
||||||
"openFile": "فتح الملف",
|
"openFile": "فتح الملف",
|
||||||
"discardChanges": "إلغاء التغييرات"
|
"discardChanges": "إلغاء التغييرات",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "تحميل الملف",
|
"downloadFile": "تحميل الملف",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "تسجيل دخول",
|
"submit": "تسجيل دخول",
|
||||||
"username": "إسم المستخدم",
|
"username": "إسم المستخدم",
|
||||||
"usernameTaken": "إسم المستخدم غير متاح",
|
"usernameTaken": "إسم المستخدم غير متاح",
|
||||||
"wrongCredentials": "بيانات دخول خاطئة"
|
"wrongCredentials": "بيانات دخول خاطئة",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "دائم",
|
"permanent": "دائم",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "فيديوهات"
|
"video": "فيديوهات"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "إدارة",
|
"admin": "إدارة",
|
||||||
"administrator": "مدير",
|
"administrator": "مدير",
|
||||||
"allowCommands": "تنفيذ اﻷوامر",
|
"allowCommands": "تنفيذ اﻷوامر",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Actualitzar",
|
"update": "Actualitzar",
|
||||||
"upload": "Pujar",
|
"upload": "Pujar",
|
||||||
"openFile": "Obrir fitxer",
|
"openFile": "Obrir fitxer",
|
||||||
"discardChanges": "Descartar"
|
"discardChanges": "Descartar",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Descarregar fitxer",
|
"downloadFile": "Descarregar fitxer",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Iniciar sessió",
|
"submit": "Iniciar sessió",
|
||||||
"username": "Usuari",
|
"username": "Usuari",
|
||||||
"usernameTaken": "Nom d'usuari no disponible",
|
"usernameTaken": "Nom d'usuari no disponible",
|
||||||
"wrongCredentials": "Usuari i/o contrasenya incorrectes"
|
"wrongCredentials": "Usuari i/o contrasenya incorrectes",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Permanent",
|
"permanent": "Permanent",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Vídeo"
|
"video": "Vídeo"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrador",
|
"administrator": "Administrador",
|
||||||
"allowCommands": "Executar comandes",
|
"allowCommands": "Executar comandes",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Aktualizovat",
|
"update": "Aktualizovat",
|
||||||
"upload": "Nahrát",
|
"upload": "Nahrát",
|
||||||
"openFile": "Otevřít soubor",
|
"openFile": "Otevřít soubor",
|
||||||
"discardChanges": "Zrušit změny"
|
"discardChanges": "Zrušit změny",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Stáhnout soubor",
|
"downloadFile": "Stáhnout soubor",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Přihlásit se",
|
"submit": "Přihlásit se",
|
||||||
"username": "Uživatelské jméno",
|
"username": "Uživatelské jméno",
|
||||||
"usernameTaken": "Uživatelské jméno již existuje",
|
"usernameTaken": "Uživatelské jméno již existuje",
|
||||||
"wrongCredentials": "Nesprávné přihlašovací údaje"
|
"wrongCredentials": "Nesprávné přihlašovací údaje",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Trvalý",
|
"permanent": "Trvalý",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Video"
|
"video": "Video"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrátor",
|
"administrator": "Administrátor",
|
||||||
"allowCommands": "Povolit příkazy",
|
"allowCommands": "Povolit příkazy",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Update",
|
"update": "Update",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"openFile": "Datei öffnen",
|
"openFile": "Datei öffnen",
|
||||||
"discardChanges": "Verwerfen"
|
"discardChanges": "Verwerfen",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Download Datei",
|
"downloadFile": "Download Datei",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Login",
|
"submit": "Login",
|
||||||
"username": "Benutzername",
|
"username": "Benutzername",
|
||||||
"usernameTaken": "Benutzername ist bereits vergeben",
|
"usernameTaken": "Benutzername ist bereits vergeben",
|
||||||
"wrongCredentials": "Falsche Zugangsdaten"
|
"wrongCredentials": "Falsche Zugangsdaten",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Permanent",
|
"permanent": "Permanent",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Video"
|
"video": "Video"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrator",
|
"administrator": "Administrator",
|
||||||
"allowCommands": "Befehle ausführen",
|
"allowCommands": "Befehle ausführen",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Ενημέρωση",
|
"update": "Ενημέρωση",
|
||||||
"upload": "Μεταφόρτωση",
|
"upload": "Μεταφόρτωση",
|
||||||
"openFile": "Άνοιγμα αρχείου",
|
"openFile": "Άνοιγμα αρχείου",
|
||||||
"discardChanges": "Discard"
|
"discardChanges": "Discard",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Λήψη αρχείου",
|
"downloadFile": "Λήψη αρχείου",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Είσοδος",
|
"submit": "Είσοδος",
|
||||||
"username": "Όνομα χρήστη",
|
"username": "Όνομα χρήστη",
|
||||||
"usernameTaken": "Το όνομα χρήστη χρησιμοποιείται ήδη",
|
"usernameTaken": "Το όνομα χρήστη χρησιμοποιείται ήδη",
|
||||||
"wrongCredentials": "Λάθος όνομα ή/και κωδικός πρόσβασης"
|
"wrongCredentials": "Λάθος όνομα ή/και κωδικός πρόσβασης",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Μόνιμο",
|
"permanent": "Μόνιμο",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Βίντεο"
|
"video": "Βίντεο"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Διαχειριστής",
|
"admin": "Διαχειριστής",
|
||||||
"administrator": "Διαχειριστής",
|
"administrator": "Διαχειριστής",
|
||||||
"allowCommands": "Εκτέλεση εντολών",
|
"allowCommands": "Εκτέλεση εντολών",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Update",
|
"update": "Update",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"openFile": "Open file",
|
"openFile": "Open file",
|
||||||
"discardChanges": "Discard"
|
"discardChanges": "Discard",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Download File",
|
"downloadFile": "Download File",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Login",
|
"submit": "Login",
|
||||||
"username": "Username",
|
"username": "Username",
|
||||||
"usernameTaken": "Username already taken",
|
"usernameTaken": "Username already taken",
|
||||||
"wrongCredentials": "Wrong credentials"
|
"wrongCredentials": "Wrong credentials",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Permanent",
|
"permanent": "Permanent",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Video"
|
"video": "Video"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrator",
|
"administrator": "Administrator",
|
||||||
"allowCommands": "Execute commands",
|
"allowCommands": "Execute commands",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"copy": "Copiar",
|
"copy": "Copiar",
|
||||||
"copyFile": "Copiar archivo",
|
"copyFile": "Copiar archivo",
|
||||||
"copyToClipboard": "Copiar al portapapeles",
|
"copyToClipboard": "Copiar al portapapeles",
|
||||||
"copyDownloadLinkToClipboard": "Copy download link to clipboard",
|
"copyDownloadLinkToClipboard": "Copiar enlace de descarga al portapapeles",
|
||||||
"create": "Crear",
|
"create": "Crear",
|
||||||
"delete": "Borrar",
|
"delete": "Borrar",
|
||||||
"download": "Descargar",
|
"download": "Descargar",
|
||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Actualizar",
|
"update": "Actualizar",
|
||||||
"upload": "Subir",
|
"upload": "Subir",
|
||||||
"openFile": "Abrir archivo",
|
"openFile": "Abrir archivo",
|
||||||
"discardChanges": "Discard"
|
"discardChanges": "Discard",
|
||||||
|
"saveChanges": "Guardar cambios"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Descargar fichero",
|
"downloadFile": "Descargar fichero",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Iniciar sesión",
|
"submit": "Iniciar sesión",
|
||||||
"username": "Usuario",
|
"username": "Usuario",
|
||||||
"usernameTaken": "Nombre usuario no disponible",
|
"usernameTaken": "Nombre usuario no disponible",
|
||||||
"wrongCredentials": "Usuario y/o contraseña incorrectos"
|
"wrongCredentials": "Usuario y/o contraseña incorrectos",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Permanente",
|
"permanent": "Permanente",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Vídeo"
|
"video": "Vídeo"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrador",
|
"administrator": "Administrador",
|
||||||
"allowCommands": "Ejecutar comandos",
|
"allowCommands": "Ejecutar comandos",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "به روز سانی",
|
"update": "به روز سانی",
|
||||||
"upload": "آپلود",
|
"upload": "آپلود",
|
||||||
"openFile": "باز کردن فایل",
|
"openFile": "باز کردن فایل",
|
||||||
"discardChanges": "لغو کردن"
|
"discardChanges": "لغو کردن",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "دانلود فایل",
|
"downloadFile": "دانلود فایل",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "ورود",
|
"submit": "ورود",
|
||||||
"username": "نام کاربری",
|
"username": "نام کاربری",
|
||||||
"usernameTaken": "نام کاربری تکراری",
|
"usernameTaken": "نام کاربری تکراری",
|
||||||
"wrongCredentials": "خطا در اعتبارسنجی"
|
"wrongCredentials": "خطا در اعتبارسنجی",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "دائمی",
|
"permanent": "دائمی",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "ویدئو "
|
"video": "ویدئو "
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrator",
|
"administrator": "Administrator",
|
||||||
"allowCommands": "اجرای دستورات",
|
"allowCommands": "اجرای دستورات",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Mettre à jour",
|
"update": "Mettre à jour",
|
||||||
"upload": "Importer",
|
"upload": "Importer",
|
||||||
"openFile": "Ouvrir le fichier",
|
"openFile": "Ouvrir le fichier",
|
||||||
"discardChanges": "Annuler"
|
"discardChanges": "Annuler",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Télécharger le fichier",
|
"downloadFile": "Télécharger le fichier",
|
||||||
@@ -77,14 +78,14 @@
|
|||||||
"noPreview": "L'aperçu n'est pas disponible pour ce fichier."
|
"noPreview": "L'aperçu n'est pas disponible pour ce fichier."
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"click": "Sélectionner un élément",
|
"click": "Sélectionner un fichier ou dossier",
|
||||||
"ctrl": {
|
"ctrl": {
|
||||||
"click": "Sélectionner plusieurs éléments",
|
"click": "Sélectionner plusieurs fichiers ou dossiers",
|
||||||
"f": "Ouvrir l'invité de recherche",
|
"f": "Ouvrir l'invité de recherche",
|
||||||
"s": "Télécharger l'élément actuel"
|
"s": "Enregistrer un fichier ou télécharger le dossier actuel"
|
||||||
},
|
},
|
||||||
"del": "Supprimer les éléments sélectionnés",
|
"del": "Supprimer les éléments sélectionnés",
|
||||||
"doubleClick": "Ouvrir un élément",
|
"doubleClick": "Ouvrir un fichier ou dossier",
|
||||||
"esc": "Désélectionner et/ou fermer la boîte de dialogue",
|
"esc": "Désélectionner et/ou fermer la boîte de dialogue",
|
||||||
"f1": "Ouvrir l'aide",
|
"f1": "Ouvrir l'aide",
|
||||||
"f2": "Renommer le fichier",
|
"f2": "Renommer le fichier",
|
||||||
@@ -98,9 +99,12 @@
|
|||||||
"passwordsDontMatch": "Les mots de passe ne concordent pas",
|
"passwordsDontMatch": "Les mots de passe ne concordent pas",
|
||||||
"signup": "S'inscrire",
|
"signup": "S'inscrire",
|
||||||
"submit": "Se connecter",
|
"submit": "Se connecter",
|
||||||
"username": "Utilisateur",
|
"username": "Utilisateur·ice",
|
||||||
"usernameTaken": "Le nom d'utilisateur est déjà pris",
|
"usernameTaken": "Le nom d'utilisateur·ice est déjà pris",
|
||||||
"wrongCredentials": "Identifiants incorrects !"
|
"wrongCredentials": "Identifiants incorrects !",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Permanent",
|
"permanent": "Permanent",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -110,7 +114,7 @@
|
|||||||
"deleteMessageMultiple": "Êtes-vous sûr de vouloir supprimer ces {count} élément(s) ?",
|
"deleteMessageMultiple": "Êtes-vous sûr de vouloir supprimer ces {count} élément(s) ?",
|
||||||
"deleteMessageSingle": "Êtes-vous sûr de vouloir supprimer cet élément ?",
|
"deleteMessageSingle": "Êtes-vous sûr de vouloir supprimer cet élément ?",
|
||||||
"deleteMessageShare": "Êtes-vous sûr de vouloir supprimer ce partage ({path}) ?",
|
"deleteMessageShare": "Êtes-vous sûr de vouloir supprimer ce partage ({path}) ?",
|
||||||
"deleteUser": "Êtes-vous sûr de vouloir supprimer cet utilisateur ?",
|
"deleteUser": "Êtes-vous sûr de vouloir supprimer cet·te utilisateur·ice ?",
|
||||||
"deleteTitle": "Supprimer",
|
"deleteTitle": "Supprimer",
|
||||||
"displayName": "Nom :",
|
"displayName": "Nom :",
|
||||||
"download": "Télécharger",
|
"download": "Télécharger",
|
||||||
@@ -120,7 +124,7 @@
|
|||||||
"filesSelected": "{count} éléments sélectionnés",
|
"filesSelected": "{count} éléments sélectionnés",
|
||||||
"lastModified": "Dernière modification",
|
"lastModified": "Dernière modification",
|
||||||
"move": "Déplacer",
|
"move": "Déplacer",
|
||||||
"moveMessage": "Choisissez l'emplacement où déplacer la sélection :",
|
"moveMessage": "Choisissez un nouveau dossier principal pour vos fichier(s)/dossier(s) :",
|
||||||
"newArchetype": "Créer un nouveau post basé sur un archétype. Votre fichier sera créé dans le dossier de contenu.",
|
"newArchetype": "Créer un nouveau post basé sur un archétype. Votre fichier sera créé dans le dossier de contenu.",
|
||||||
"newDir": "Nouveau dossier",
|
"newDir": "Nouveau dossier",
|
||||||
"newDirMessage": "Nom du nouveau dossier :",
|
"newDirMessage": "Nom du nouveau dossier :",
|
||||||
@@ -154,13 +158,14 @@
|
|||||||
"video": "Vidéo"
|
"video": "Vidéo"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrateur",
|
"administrator": "Administrateur·ice",
|
||||||
"allowCommands": "Exécuter des commandes",
|
"allowCommands": "Exécuter des commandes",
|
||||||
"allowEdit": "Éditer, renommer et supprimer des fichiers ou des dossiers",
|
"allowEdit": "Éditer, renommer et supprimer des fichiers ou des dossiers",
|
||||||
"allowNew": "Créer de nouveaux fichiers et dossiers",
|
"allowNew": "Créer de nouveaux fichiers et dossiers",
|
||||||
"allowPublish": "Publier de nouveaux posts et pages",
|
"allowPublish": "Publier de nouveaux posts et pages",
|
||||||
"allowSignup": "Autoriser les utilisateurs à s'inscrire",
|
"allowSignup": "Autoriser les utilisateur·ices à s'inscrire",
|
||||||
"avoidChanges": "(Laisser vide pour conserver l'actuel)",
|
"avoidChanges": "(Laisser vide pour conserver l'actuel)",
|
||||||
"branding": "Image de marque",
|
"branding": "Image de marque",
|
||||||
"brandingDirectoryPath": "Chemin du dossier d'image de marque",
|
"brandingDirectoryPath": "Chemin du dossier d'image de marque",
|
||||||
@@ -169,17 +174,17 @@
|
|||||||
"commandRunner": "Exécuteur de commandes",
|
"commandRunner": "Exécuteur de commandes",
|
||||||
"commandRunnerHelp": "Ici, vous pouvez définir les commandes qui seront exécutées lors des événements nommés précédemments. Vous devez en écrire une par ligne. Les variables d'environnement {0} et {1} seront disponibles, {0} étant relatif à {1}. Pour plus d'informations sur cette fonctionnalité et les variables d'environnement disponibles, veuillez lire la {2}.",
|
"commandRunnerHelp": "Ici, vous pouvez définir les commandes qui seront exécutées lors des événements nommés précédemments. Vous devez en écrire une par ligne. Les variables d'environnement {0} et {1} seront disponibles, {0} étant relatif à {1}. Pour plus d'informations sur cette fonctionnalité et les variables d'environnement disponibles, veuillez lire la {2}.",
|
||||||
"commandsUpdated": "Commandes mises à jour !",
|
"commandsUpdated": "Commandes mises à jour !",
|
||||||
"createUserDir": "Créer automatiquement un dossier pour l'utilisateur",
|
"createUserDir": "Créer automatiquement un dossier pour l'utilisateur·ice",
|
||||||
"minimumPasswordLength": "Minimum password length",
|
"minimumPasswordLength": "Taille minimale du mot de passe",
|
||||||
"tusUploads": "Uploads segmentés",
|
"tusUploads": "Uploads segmentés",
|
||||||
"tusUploadsHelp": "File Browser prend en charge les uploads segmentés afin de permettre une gestion efficace, fiable et reprenable sur des réseaux instables.",
|
"tusUploadsHelp": "File Browser prend en charge les uploads segmentés afin de permettre une gestion efficace, fiable et reprenable sur des réseaux instables.",
|
||||||
"tusUploadsChunkSize": "Taille maximale autorisée par segment (les uploads directs seront utilisés pour les fichiers plus petits). Vous pouvez entrer un entier en octets ou une chaîne telle que 10MB, 1GB, etc.",
|
"tusUploadsChunkSize": "Taille maximale autorisée par segment (les uploads directs seront utilisés pour les fichiers plus petits). Vous pouvez entrer un entier en octets ou une chaîne telle que 10MB, 1GB, etc.",
|
||||||
"tusUploadsRetryCount": "Nombre de tentatives en cas d'échec d'un segment.",
|
"tusUploadsRetryCount": "Nombre de tentatives en cas d'échec d'un segment.",
|
||||||
"userHomeBasePath": "Chemin de base pour les répertoires personnels des utilisateurs",
|
"userHomeBasePath": "Chemin de base pour les dossiers personnels des utilisateur·ices",
|
||||||
"userScopeGenerationPlaceholder": "Le périmètre sera généré automatiquement",
|
"userScopeGenerationPlaceholder": "Le périmètre sera généré automatiquement",
|
||||||
"createUserHomeDirectory": "Créer le répertoire personnel de l'utilisateur",
|
"createUserHomeDirectory": "Créer le dossier personnel de l'utilisateur·ice",
|
||||||
"customStylesheet": "Feuille de style personnalisée",
|
"customStylesheet": "Feuille de style personnalisée",
|
||||||
"defaultUserDescription": "Paramètres par défaut pour les nouveaux utilisateurs.",
|
"defaultUserDescription": "Paramètres par défaut pour les nouveaux utilisateur·ices.",
|
||||||
"disableExternalLinks": "Désactiver les liens externes (sauf la documentation)",
|
"disableExternalLinks": "Désactiver les liens externes (sauf la documentation)",
|
||||||
"disableUsedDiskPercentage": "Désactiver le graphique de pourcentage d'utilisation du disque",
|
"disableUsedDiskPercentage": "Désactiver le graphique de pourcentage d'utilisation du disque",
|
||||||
"documentation": "documentation",
|
"documentation": "documentation",
|
||||||
@@ -188,12 +193,12 @@
|
|||||||
"executeOnShellDescription": "Par défaut, File Browser exécute les commandes en appelant directement leurs binaires. Si vous voulez les exécuter sur un shell à la place (comme Bash ou PowerShell), vous pouvez le définir ici avec les arguments et les drapeaux requis. S'il est défini, la commande que vous exécutez sera ajoutée en tant qu'argument. Cela s'applique à la fois aux commandes utilisateur et aux crochets d'événements.",
|
"executeOnShellDescription": "Par défaut, File Browser exécute les commandes en appelant directement leurs binaires. Si vous voulez les exécuter sur un shell à la place (comme Bash ou PowerShell), vous pouvez le définir ici avec les arguments et les drapeaux requis. S'il est défini, la commande que vous exécutez sera ajoutée en tant qu'argument. Cela s'applique à la fois aux commandes utilisateur et aux crochets d'événements.",
|
||||||
"globalRules": "Il s'agit d'un ensemble global de règles d'autorisation et d'interdiction. Elles s'appliquent à tous les utilisateurs. Vous pouvez définir des règles spécifiques sur les paramètres de chaque utilisateur pour remplacer celles-ci.",
|
"globalRules": "Il s'agit d'un ensemble global de règles d'autorisation et d'interdiction. Elles s'appliquent à tous les utilisateurs. Vous pouvez définir des règles spécifiques sur les paramètres de chaque utilisateur pour remplacer celles-ci.",
|
||||||
"globalSettings": "Paramètres globaux",
|
"globalSettings": "Paramètres globaux",
|
||||||
"hideDotfiles": "Cacher les fichiers de configuration utilisateur (dotfiles)",
|
"hideDotfiles": "Cacher les fichiers de configuration commançant par un point",
|
||||||
"insertPath": "Insérer le chemin",
|
"insertPath": "Insérer le chemin",
|
||||||
"insertRegex": "Insérer une expression régulière",
|
"insertRegex": "Insérer une expression régulière",
|
||||||
"instanceName": "Nom de l'instance",
|
"instanceName": "Nom de l'instance",
|
||||||
"language": "Langue",
|
"language": "Langue",
|
||||||
"lockPassword": "Empêcher l'utilisateur de changer son mot de passe",
|
"lockPassword": "Empêcher l'utilisateur·ice de changer son mot de passe",
|
||||||
"newPassword": "Votre nouveau mot de passe",
|
"newPassword": "Votre nouveau mot de passe",
|
||||||
"newPasswordConfirm": "Confirmation du nouveau mot de passe",
|
"newPasswordConfirm": "Confirmation du nouveau mot de passe",
|
||||||
"newUser": "Nouvel utilisateur",
|
"newUser": "Nouvel utilisateur",
|
||||||
@@ -210,13 +215,13 @@
|
|||||||
"share": "Partager des fichiers"
|
"share": "Partager des fichiers"
|
||||||
},
|
},
|
||||||
"permissions": "Permissions",
|
"permissions": "Permissions",
|
||||||
"permissionsHelp": "Vous pouvez définir l'utilisateur comme étant un administrateur ou encore choisir les permissions individuellement. Si vous sélectionnez \"Administrateur\", toutes les autres options seront automatiquement activées. La gestion des utilisateurs est un privilège que seul l'administrateur possède.\n",
|
"permissionsHelp": "Vous pouvez définir l'utilisateur·ice comme étant administrateur·ice ou encore choisir les permissions individuellement. Si vous sélectionnez \"Administrateur·ice\", toutes les autres options seront automatiquement activées. La gestion des utilisateur·ices est un privilège que seul l'administrateur·ice possède.\n",
|
||||||
"profileSettings": "Paramètres du profil",
|
"profileSettings": "Paramètres du profil",
|
||||||
"ruleExample1": "Bloque l'accès à tous les fichiers commençant par un point (comme par exemple .git, .gitignore) dans tous les dossiers",
|
"ruleExample1": "Bloque l'accès à tous les fichiers commençant par un point (comme par exemple .git, .gitignore) dans tous les dossiers.\n",
|
||||||
"ruleExample2": "Bloque l'accès au fichier nommé \"Caddyfile\" à la racine du dossier utilisateur",
|
"ruleExample2": "Bloque l'accès au fichier nommé \"Caddyfile\" à la racine du dossier utilisateur·ice.",
|
||||||
"rules": "Règles",
|
"rules": "Règles",
|
||||||
"rulesHelp": "Vous pouvez définir ici un ensemble de règles pour cet utilisateur. Les fichiers bloqués ne seront pas affichés et ne seront pas accessibles par l'utilisateur. Les expressions régulières sont supportées et les chemins d'accès sont relatifs par rapport au dossier de l'utilisateur.\n",
|
"rulesHelp": "Vous pouvez définir ici un ensemble de règles pour cet utilisateur·ice. Les fichiers bloqués ne seront pas affichés et ne seront pas accessibles par l'utilisateur·ice. Les expressions régulières sont supportées et les chemins d'accès sont relatifs par rapport au dossier de l'utilisateur·ice.\n",
|
||||||
"scope": "Portée du dossier utilisateur",
|
"scope": "Portée du dossier utilisateur·ice",
|
||||||
"setDateFormat": "Définir le format de la date",
|
"setDateFormat": "Définir le format de la date",
|
||||||
"settingsUpdated": "Les paramètres ont été mis à jour !",
|
"settingsUpdated": "Les paramètres ont été mis à jour !",
|
||||||
"shareDuration": "Durée du partage",
|
"shareDuration": "Durée du partage",
|
||||||
@@ -224,21 +229,21 @@
|
|||||||
"shareDeleted": "Partage supprimé !",
|
"shareDeleted": "Partage supprimé !",
|
||||||
"singleClick": "Utiliser un simple clic pour ouvrir les fichiers et les dossiers",
|
"singleClick": "Utiliser un simple clic pour ouvrir les fichiers et les dossiers",
|
||||||
"themes": {
|
"themes": {
|
||||||
"default": "System default",
|
"default": "Par défaut du système",
|
||||||
"dark": "Sombre",
|
"dark": "Sombre",
|
||||||
"light": "Clair",
|
"light": "Clair",
|
||||||
"title": "Thème"
|
"title": "Thème"
|
||||||
},
|
},
|
||||||
"user": "Utilisateur",
|
"user": "Utilisateur·ice",
|
||||||
"userCommands": "Commandes",
|
"userCommands": "Commandes",
|
||||||
"userCommandsHelp": "Une liste séparée par des espaces des commandes permises pour l'utilisateur. Exemple :\n",
|
"userCommandsHelp": "Une liste séparée par des espaces des commandes permises pour l'utilisateur·ice. Exemple :\n",
|
||||||
"userCreated": "Utilisateur créé !",
|
"userCreated": "Utilisateur·ice créé !",
|
||||||
"userDefaults": "Paramètres par défaut de l'utilisateur",
|
"userDefaults": "Paramètres par défaut de l'utilisateur.ice",
|
||||||
"userDeleted": "Utilisateur supprimé !",
|
"userDeleted": "Utilisateur·ice supprimé !",
|
||||||
"userManagement": "Gestion des utilisateurs",
|
"userManagement": "Gestion des utilisateur·ices",
|
||||||
"userUpdated": "Utilisateur mis à jour !",
|
"userUpdated": "Utilisateur·ice mis à jour !",
|
||||||
"username": "Nom d'utilisateur",
|
"username": "Nom d'utilisateur·ice",
|
||||||
"users": "Utilisateurs"
|
"users": "Utilisateur·ices"
|
||||||
},
|
},
|
||||||
"sidebar": {
|
"sidebar": {
|
||||||
"help": "Aide",
|
"help": "Aide",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "עדכון",
|
"update": "עדכון",
|
||||||
"upload": "העלאה",
|
"upload": "העלאה",
|
||||||
"openFile": "פתח קובץ",
|
"openFile": "פתח קובץ",
|
||||||
"discardChanges": "זריקת השינויים"
|
"discardChanges": "זריקת השינויים",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "הורד קובץ",
|
"downloadFile": "הורד קובץ",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "התחברות",
|
"submit": "התחברות",
|
||||||
"username": "שם משתמש",
|
"username": "שם משתמש",
|
||||||
"usernameTaken": "שם המשתמש כבר קיים",
|
"usernameTaken": "שם המשתמש כבר קיים",
|
||||||
"wrongCredentials": "פרטי התחברות שגויים"
|
"wrongCredentials": "פרטי התחברות שגויים",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "קבוע",
|
"permanent": "קבוע",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "וידאו"
|
"video": "וידאו"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "מנהל",
|
"admin": "מנהל",
|
||||||
"administrator": "מנהל ראשי",
|
"administrator": "מנהל ראשי",
|
||||||
"allowCommands": "הפעלת פקודות",
|
"allowCommands": "הפעלת פקודות",
|
||||||
|
|||||||
271
frontend/src/i18n/hr.json
Normal file
@@ -0,0 +1,271 @@
|
|||||||
|
{
|
||||||
|
"buttons": {
|
||||||
|
"cancel": "Otkaži",
|
||||||
|
"clear": "Očisti",
|
||||||
|
"close": "Zatvori",
|
||||||
|
"continue": "Nastavi",
|
||||||
|
"copy": "Kopiraj",
|
||||||
|
"copyFile": "Kopiraj datoteku",
|
||||||
|
"copyToClipboard": "Kopiraj u međuspremnik",
|
||||||
|
"copyDownloadLinkToClipboard": "Kopiraj poveznicu za preuzimanje u međuspremnik",
|
||||||
|
"create": "Stvori",
|
||||||
|
"delete": "Izbriši",
|
||||||
|
"download": "Preuzmi",
|
||||||
|
"file": "Datoteka",
|
||||||
|
"folder": "Mapa",
|
||||||
|
"fullScreen": "Prebaci na cijeli zaslon",
|
||||||
|
"hideDotfiles": "Sakrij datoteke koje započinju točkom",
|
||||||
|
"info": "Info",
|
||||||
|
"more": "Više",
|
||||||
|
"move": "Premjesti",
|
||||||
|
"moveFile": "Premjesti datoteku",
|
||||||
|
"new": "Novo",
|
||||||
|
"next": "Sljedeće",
|
||||||
|
"ok": "OK",
|
||||||
|
"permalink": "Dohvati trajnu poveznicu",
|
||||||
|
"previous": "Prethodno",
|
||||||
|
"preview": "Pregled",
|
||||||
|
"publish": "Objavi",
|
||||||
|
"rename": "Preimenuj",
|
||||||
|
"replace": "Zamijeni",
|
||||||
|
"reportIssue": "Prijavi grešku",
|
||||||
|
"save": "Spremi",
|
||||||
|
"schedule": "Zakaži",
|
||||||
|
"search": "Pretraži",
|
||||||
|
"select": "Označi",
|
||||||
|
"selectMultiple": "Označi više",
|
||||||
|
"share": "Podijeli",
|
||||||
|
"shell": "Promijeni ljusku",
|
||||||
|
"submit": "Predaj",
|
||||||
|
"switchView": "Promijeni prikaz",
|
||||||
|
"toggleSidebar": "Prebaci bočnu traku",
|
||||||
|
"update": "Ažuriraj",
|
||||||
|
"upload": "Prenesi",
|
||||||
|
"openFile": "Otvori datoteku",
|
||||||
|
"discardChanges": "Odbaci",
|
||||||
|
"saveChanges": "Spremi promjene"
|
||||||
|
},
|
||||||
|
"download": {
|
||||||
|
"downloadFile": "Preuzmi Datoteku",
|
||||||
|
"downloadFolder": "Preuzmi Mapu",
|
||||||
|
"downloadSelected": "Preuzmi Odabrano"
|
||||||
|
},
|
||||||
|
"upload": {
|
||||||
|
"abortUpload": "Jeste li sigurni da hoćete otkazati?"
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"forbidden": "Nemate dopuštenje pristupiti ovome.",
|
||||||
|
"internal": "Nešto je stvarno pošlo po zlu.",
|
||||||
|
"notFound": "Lokacija ne može biti dohvaćena.",
|
||||||
|
"connection": "Poslužitelj ne može biti dohvaćen."
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"body": "Tijelo",
|
||||||
|
"closePreview": "Zatvori pregled",
|
||||||
|
"files": "Datoteke",
|
||||||
|
"folders": "Mape",
|
||||||
|
"home": "Dom",
|
||||||
|
"lastModified": "Zadnje izmijenjeno",
|
||||||
|
"loading": "Učitavanje...",
|
||||||
|
"lonely": "Ovdje je tako prazno...",
|
||||||
|
"metadata": "Metapodaci",
|
||||||
|
"multipleSelectionEnabled": "Višestruk odabir",
|
||||||
|
"name": "Naziv",
|
||||||
|
"size": "Veličina",
|
||||||
|
"sortByLastModified": "Sortiraj po zadnjoj izmjeni",
|
||||||
|
"sortByName": "Sortiraj po nazivu",
|
||||||
|
"sortBySize": "Sortiraj po veličini",
|
||||||
|
"noPreview": "Pregled nije dostupan za ovu datoteku."
|
||||||
|
},
|
||||||
|
"help": {
|
||||||
|
"click": "odaberi datoteku ili mapu",
|
||||||
|
"ctrl": {
|
||||||
|
"click": "odaberi više datoteka ili mapa",
|
||||||
|
"f": "tražilica",
|
||||||
|
"s": "spremi datoteku ili preuzmi trenutnu mapu"
|
||||||
|
},
|
||||||
|
"del": "izbriši odabrane stavke",
|
||||||
|
"doubleClick": "otvori datoteku ili mapu",
|
||||||
|
"esc": "očisti odabir i/ili zatvori upit",
|
||||||
|
"f1": "ova informacija",
|
||||||
|
"f2": "preimenuj datoteku",
|
||||||
|
"help": "Pomoć"
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
|
"createAnAccount": "Stvori korisnički račun",
|
||||||
|
"loginInstead": "Imam korisnički račun",
|
||||||
|
"password": "Lozinka",
|
||||||
|
"passwordConfirm": "Potvrda lozinke",
|
||||||
|
"passwordsDontMatch": "Lozinke se ne podudaraju",
|
||||||
|
"signup": "Registracija",
|
||||||
|
"submit": "Prijava",
|
||||||
|
"username": "Korisničko ime",
|
||||||
|
"usernameTaken": "Korisničko ime zauzeto",
|
||||||
|
"wrongCredentials": "Neispravno korisničko ime/lozinka",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "Odjavljeni ste zbog neaktivnosti."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"permanent": "Trajan",
|
||||||
|
"prompts": {
|
||||||
|
"copy": "Kopiraj",
|
||||||
|
"copyMessage": "Odaberite lokaciju za kopiranje datoteka:",
|
||||||
|
"currentlyNavigating": "Trenutno navigiranje na:",
|
||||||
|
"deleteMessageMultiple": "Jeste li sigurni da želite izbrisati datoteke: {count}?",
|
||||||
|
"deleteMessageSingle": "Jeste li sigurni da hoćete izbrisati ovu datoteku/mapu?",
|
||||||
|
"deleteMessageShare": "Jeste li sigurni da hoćete izbrisati ovo dijeljenje({path})?",
|
||||||
|
"deleteUser": "Jeste li sigurni da hoćete izbrisati ovaj korisnički račun?",
|
||||||
|
"deleteTitle": "Izbriši datoteke",
|
||||||
|
"displayName": "Prikazno Ime:",
|
||||||
|
"download": "Preuzmi datoteke",
|
||||||
|
"downloadMessage": "Odaberite format za preuzimanje.",
|
||||||
|
"error": "Nešto je pošlo po zlu",
|
||||||
|
"fileInfo": "Informacije o datoteci",
|
||||||
|
"filesSelected": "{count} datoteka odabrana.",
|
||||||
|
"lastModified": "Zadnje izmijenjeno",
|
||||||
|
"move": "Premjesti",
|
||||||
|
"moveMessage": "Odaberite novi dom za Vašu datoteku(e)/mapu(e):",
|
||||||
|
"newArchetype": "Stvorite novu objavu na temelju arhetipu. Vaša datoteka bit će stvorena u mapi sadržaja.",
|
||||||
|
"newDir": "Nova mapa",
|
||||||
|
"newDirMessage": "Imenujte Vašu novu mapu.",
|
||||||
|
"newFile": "Nova datoteka",
|
||||||
|
"newFileMessage": "Imenujte Vašu novu datoteku.",
|
||||||
|
"numberDirs": "Broj mapa",
|
||||||
|
"numberFiles": "Broj datoteka",
|
||||||
|
"rename": "Preimenuj",
|
||||||
|
"renameMessage": "Umetni novo ime za",
|
||||||
|
"replace": "Zamijeni",
|
||||||
|
"replaceMessage": "Jedna od datoteka koju pokušavate prenijeti ima sukobljavajući naziv. Želite li preskočiti ovu datoteku i nastaviti s prijenosom ili zamijeniti postojeću datoteku?\n",
|
||||||
|
"schedule": "Zakaži",
|
||||||
|
"scheduleMessage": "Odaberite datum i vrijeme za zakazivanje ove objave.",
|
||||||
|
"show": "Prikaži",
|
||||||
|
"size": "Veličina",
|
||||||
|
"upload": "Prenesi",
|
||||||
|
"uploadFiles": "Prenošenje {files} datoteka...",
|
||||||
|
"uploadMessage": "Odaberite opciju za prijenos.",
|
||||||
|
"optionalPassword": "Opcionalna lozinka",
|
||||||
|
"resolution": "Rezolucija",
|
||||||
|
"discardEditorChanges": "Jeste li sigurni da želite odbaciti promjene koje ste napravili?"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"images": "Slike",
|
||||||
|
"music": "Glazba",
|
||||||
|
"pdf": "PDF",
|
||||||
|
"pressToSearch": "Pritisnite enter za pretraživanje...",
|
||||||
|
"search": "Pretraživanje...",
|
||||||
|
"typeToSearch": "Tipkajte za pretraživanje...",
|
||||||
|
"types": "Tipovi",
|
||||||
|
"video": "Video"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
|
"admin": "Admin",
|
||||||
|
"administrator": "Administrator",
|
||||||
|
"allowCommands": "Izvrši naredbe",
|
||||||
|
"allowEdit": "Uredi, preimenuj i izbriši datoteke ili mape",
|
||||||
|
"allowNew": "Stvori nove datoteke i mape",
|
||||||
|
"allowPublish": "Objavi nove objave i stranice",
|
||||||
|
"allowSignup": "Dopusti registraciju korisnicima",
|
||||||
|
"avoidChanges": "(ostavite prazno kako biste izbjegli promjene)",
|
||||||
|
"branding": "Brendiranje",
|
||||||
|
"brandingDirectoryPath": "Put brendiranja",
|
||||||
|
"brandingHelp": "Možete prilagoditi izgled i funkcionalnost Vašeg File Browsera mijenjanjem njegovog naziva, zamjenom logotipa, dodavanjem prilagođenih stilova pa čak i onemogućavanjem vanjskih poveznica na GitHub.\nZa više informacija o prilagođenome brendiranju pogledajte {0}.",
|
||||||
|
"changePassword": "Promjena lozinke",
|
||||||
|
"commandRunner": "Izvršitelj naredbi",
|
||||||
|
"commandRunnerHelp": "Ovdje možete postaviti naredbe koje se izvršuju u imenovanim događajima. Morate napisati jednu po liniji. Varijable okruženja {0} i {1} bit će dostupne, tako da je {0} relativna {1}. Za više informacija o ovoj značajci pogledajte {2}.",
|
||||||
|
"commandsUpdated": "Naredbe ažurirane!",
|
||||||
|
"createUserDir": "Automatsko stvaranje kućne mape korisnika pri dodavanju novog korisnika",
|
||||||
|
"minimumPasswordLength": "Minimalna duljina lozinke",
|
||||||
|
"tusUploads": "Segmentirani prijenosi",
|
||||||
|
"tusUploadsHelp": "File Browser podržava segmentirane prijenose datoteka, omogućavajući stvaranje učinkovitih, pouzdanih, obnovljivih i segmentiranih prijenosa datoteka čak i na nepouzdanim mrežama.",
|
||||||
|
"tusUploadsChunkSize": "Naznačuje maksimalnu veličinu zahtjeva (direktni prijenosi bit će korišteni za manje prijenose). Možete unijeti cijeli broj koji označava veličinu bajta ili niz znakova poput 10MB, 1GB itd.",
|
||||||
|
"tusUploadsRetryCount": "Broj ponovnih pokušaja ako se dio ne uspije prenijeti.",
|
||||||
|
"userHomeBasePath": "Bazni put za kućne mape korisnika",
|
||||||
|
"userScopeGenerationPlaceholder": "Opseg će se automatski generirati",
|
||||||
|
"createUserHomeDirectory": "Stvori kućnu mapu korisnika",
|
||||||
|
"customStylesheet": "Prilagođeni Stylesheet",
|
||||||
|
"defaultUserDescription": "Zadane postavke za nove korisnike.",
|
||||||
|
"disableExternalLinks": "Onemogući vanjske poveznice (osim dokumentacije)",
|
||||||
|
"disableUsedDiskPercentage": "Onemogući graf iskorištenosti diska",
|
||||||
|
"documentation": "dokumentacija",
|
||||||
|
"examples": "Primjeri",
|
||||||
|
"executeOnShell": "Izvrši u ljusci",
|
||||||
|
"executeOnShellDescription": "Po zadanim postavkama, File Browser izvršava naredbe izravnim pozivanjem njihovih binarnih datoteka. Ako ih želite izvršiti u ljusci (kao što su Bash ili PowerShell), možete ih definirati ovdje s potrebnim argumentima i oznakama. Ako je postavljena, naredba koju izvršavate bit će dodana kao argument. To se odnosi i na korisničke naredbe i na događajne kuke.",
|
||||||
|
"globalRules": "Ovo je globalan skup pravila dopuštanja i zabrane. Primjenjuju se na svakog korisnika. Moguće je definirati specifična pravila u postavkama svakog korisnika da biste nadjačali ove postavke.",
|
||||||
|
"globalSettings": "Globalne postavke",
|
||||||
|
"hideDotfiles": "Sakrij datoteke koje započinju točkom",
|
||||||
|
"insertPath": "Umetni put",
|
||||||
|
"insertRegex": "Umetni regex izraz",
|
||||||
|
"instanceName": "Naziv instance",
|
||||||
|
"language": "Jezik",
|
||||||
|
"lockPassword": "Onemogući mijenjanje lozinke korisniku",
|
||||||
|
"newPassword": "Vaša nova lozinka",
|
||||||
|
"newPasswordConfirm": "Potvrdite Vašu novu lozinku",
|
||||||
|
"newUser": "Novi Korisnik",
|
||||||
|
"password": "Lozinka",
|
||||||
|
"passwordUpdated": "Lozinka ažurirana!",
|
||||||
|
"path": "Put",
|
||||||
|
"perm": {
|
||||||
|
"create": "Stvaranje datoteka i mapa",
|
||||||
|
"delete": "Brisanje datoteka i mapa",
|
||||||
|
"download": "Preuzimanje",
|
||||||
|
"execute": "Izvršavanje naredbi",
|
||||||
|
"modify": "Uređivanje datoteka",
|
||||||
|
"rename": "Preimenovanje ili premještanje datoteka i mapa",
|
||||||
|
"share": "Dijeljenje datoteka"
|
||||||
|
},
|
||||||
|
"permissions": "Dopuštenja",
|
||||||
|
"permissionsHelp": "Korisnika možete postaviti administratorom ili odabrati dopuštenja individualno. Odabirom na \"Administrator\", sve druge opcije bit će automatski odabrane. Upravljanje korisnicima ostaje privilegija administratora.\n",
|
||||||
|
"profileSettings": "Postavke profila",
|
||||||
|
"ruleExample1": "onemogućava pristup svakoj datoteci koja započinje točkom (poput .git, .gitignore) u svakoj mapi.\n",
|
||||||
|
"ruleExample2": "blokira pristup datoteci naziva Caddyfile na korijenu opsega.",
|
||||||
|
"rules": "Pravila",
|
||||||
|
"rulesHelp": "Ovdje možete definirati skup pravila dopuštanja i zabrane za ovog specifičnog korisnika. Blokirane datoteke neće se prikazivati u popisima i neće biti dostupne korisniku. Podržavamo regex i puteve relativne opsegu korisnika.\n",
|
||||||
|
"scope": "Opseg",
|
||||||
|
"setDateFormat": "Odredi točan format datuma",
|
||||||
|
"settingsUpdated": "Postavke ažurirane!",
|
||||||
|
"shareDuration": "Podijeli Trajanje",
|
||||||
|
"shareManagement": "Upravljanje Dijeljenjem",
|
||||||
|
"shareDeleted": "Podjela izbrisana!",
|
||||||
|
"singleClick": "Koristi jednostruke klikove za otvaranje datoteka i mapa",
|
||||||
|
"themes": {
|
||||||
|
"default": "Zadano - Sustav",
|
||||||
|
"dark": "Tamno",
|
||||||
|
"light": "Svijetlo",
|
||||||
|
"title": "Tema"
|
||||||
|
},
|
||||||
|
"user": "Korisnik",
|
||||||
|
"userCommands": "Naredbe",
|
||||||
|
"userCommandsHelp": "Popis dostupnih naredbi za ovog korisnika. Primjer:\n",
|
||||||
|
"userCreated": "Korisnik stvoren!",
|
||||||
|
"userDefaults": "Zadane postavke korisnika",
|
||||||
|
"userDeleted": "Korisnik izbrisan!",
|
||||||
|
"userManagement": "Upravljanje Korisnicima",
|
||||||
|
"userUpdated": "Korisnik ažuriran!",
|
||||||
|
"username": "Korisničko ime",
|
||||||
|
"users": "Korisnici"
|
||||||
|
},
|
||||||
|
"sidebar": {
|
||||||
|
"help": "Pomoć",
|
||||||
|
"hugoNew": "Hugo New",
|
||||||
|
"login": "Prijava",
|
||||||
|
"logout": "Odjava",
|
||||||
|
"myFiles": "Moje datoteke",
|
||||||
|
"newFile": "Nova datoteka",
|
||||||
|
"newFolder": "Nova mapa",
|
||||||
|
"preview": "Pregled",
|
||||||
|
"settings": "Postavke",
|
||||||
|
"signup": "Registracija",
|
||||||
|
"siteSettings": "Postavke stranice"
|
||||||
|
},
|
||||||
|
"success": {
|
||||||
|
"linkCopied": "Poveznica kopirana!"
|
||||||
|
},
|
||||||
|
"time": {
|
||||||
|
"days": "Dani",
|
||||||
|
"hours": "Sati",
|
||||||
|
"minutes": "Minute",
|
||||||
|
"seconds": "Sekunde",
|
||||||
|
"unit": "Jedinica vremena"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Frissítés",
|
"update": "Frissítés",
|
||||||
"upload": "Feltöltés",
|
"upload": "Feltöltés",
|
||||||
"openFile": "Fájl megnyitása",
|
"openFile": "Fájl megnyitása",
|
||||||
"discardChanges": "Discard"
|
"discardChanges": "Discard",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Fájl letöltése",
|
"downloadFile": "Fájl letöltése",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Belépés",
|
"submit": "Belépés",
|
||||||
"username": "Felhasználói név",
|
"username": "Felhasználói név",
|
||||||
"usernameTaken": "A felhasználói név már foglalt",
|
"usernameTaken": "A felhasználói név már foglalt",
|
||||||
"wrongCredentials": "Hibás hitelesítő adatok"
|
"wrongCredentials": "Hibás hitelesítő adatok",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Állandó",
|
"permanent": "Állandó",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Videó"
|
"video": "Videó"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Adminisztrátor",
|
"administrator": "Adminisztrátor",
|
||||||
"allowCommands": "Parancsok futtatása",
|
"allowCommands": "Parancsok futtatása",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import("dayjs/locale/en");
|
|||||||
import("dayjs/locale/es");
|
import("dayjs/locale/es");
|
||||||
import("dayjs/locale/fr");
|
import("dayjs/locale/fr");
|
||||||
import("dayjs/locale/he");
|
import("dayjs/locale/he");
|
||||||
|
import("dayjs/locale/hr");
|
||||||
import("dayjs/locale/hu");
|
import("dayjs/locale/hu");
|
||||||
import("dayjs/locale/is");
|
import("dayjs/locale/is");
|
||||||
import("dayjs/locale/it");
|
import("dayjs/locale/it");
|
||||||
@@ -41,6 +42,9 @@ export function detectLocale() {
|
|||||||
case /^he\b/.test(locale):
|
case /^he\b/.test(locale):
|
||||||
locale = "he";
|
locale = "he";
|
||||||
break;
|
break;
|
||||||
|
case /^hr\b/.test(locale):
|
||||||
|
locale = "hr";
|
||||||
|
break;
|
||||||
case /^hu\b/.test(locale):
|
case /^hu\b/.test(locale):
|
||||||
locale = "hu";
|
locale = "hu";
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Vista",
|
"update": "Vista",
|
||||||
"upload": "Hlaða upp",
|
"upload": "Hlaða upp",
|
||||||
"openFile": "Open file",
|
"openFile": "Open file",
|
||||||
"discardChanges": "Discard"
|
"discardChanges": "Discard",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Sækja skjal",
|
"downloadFile": "Sækja skjal",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Innskráning",
|
"submit": "Innskráning",
|
||||||
"username": "Notendanafn",
|
"username": "Notendanafn",
|
||||||
"usernameTaken": "Þetta norendanafn er þegar í notkun",
|
"usernameTaken": "Þetta norendanafn er þegar í notkun",
|
||||||
"wrongCredentials": "Rangar notendaupplýsingar"
|
"wrongCredentials": "Rangar notendaupplýsingar",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Varanlegt",
|
"permanent": "Varanlegt",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Myndbönd"
|
"video": "Myndbönd"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Stjórnandi",
|
"admin": "Stjórnandi",
|
||||||
"administrator": "Stjórnandi",
|
"administrator": "Stjórnandi",
|
||||||
"allowCommands": "Senda skipanir",
|
"allowCommands": "Senda skipanir",
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
"copy": "Copia",
|
"copy": "Copia",
|
||||||
"copyFile": "Copia file",
|
"copyFile": "Copia file",
|
||||||
"copyToClipboard": "Copia negli appunti",
|
"copyToClipboard": "Copia negli appunti",
|
||||||
"copyDownloadLinkToClipboard": "Copy download link to clipboard",
|
"copyDownloadLinkToClipboard": "Copia link di scarica negli appunti",
|
||||||
"create": "Crea",
|
"create": "Crea",
|
||||||
"delete": "Elimina",
|
"delete": "Elimina",
|
||||||
"download": "Scarica",
|
"download": "Scarica",
|
||||||
"file": "File",
|
"file": "File",
|
||||||
"folder": "Folder",
|
"folder": "Cartella",
|
||||||
"fullScreen": "Toggle full screen",
|
"fullScreen": "Abilita schermo intero",
|
||||||
"hideDotfiles": "Nascondi dotfile",
|
"hideDotfiles": "Nascondi dotfile",
|
||||||
"info": "Informazioni",
|
"info": "Informazioni",
|
||||||
"more": "Altro",
|
"more": "Altro",
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"permalink": "Ottieni link permanente",
|
"permalink": "Ottieni link permanente",
|
||||||
"previous": "Precedente",
|
"previous": "Precedente",
|
||||||
"preview": "Preview",
|
"preview": "Anteprima",
|
||||||
"publish": "Publica",
|
"publish": "Publica",
|
||||||
"rename": "Rinomina",
|
"rename": "Rinomina",
|
||||||
"replace": "Sostituisci",
|
"replace": "Sostituisci",
|
||||||
@@ -36,13 +36,14 @@
|
|||||||
"selectMultiple": "Seleziona molteplici",
|
"selectMultiple": "Seleziona molteplici",
|
||||||
"share": "Condividi",
|
"share": "Condividi",
|
||||||
"shell": "Mostra/nascondi shell",
|
"shell": "Mostra/nascondi shell",
|
||||||
"submit": "Submit",
|
"submit": "Invia",
|
||||||
"switchView": "Cambia vista",
|
"switchView": "Cambia vista",
|
||||||
"toggleSidebar": "Mostra/nascondi la barra laterale",
|
"toggleSidebar": "Mostra/nascondi la barra laterale",
|
||||||
"update": "Aggiorna",
|
"update": "Aggiorna",
|
||||||
"upload": "Carica",
|
"upload": "Carica",
|
||||||
"openFile": "Open file",
|
"openFile": "Apri file",
|
||||||
"discardChanges": "Discard"
|
"discardChanges": "Ignora",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Scarica file",
|
"downloadFile": "Scarica file",
|
||||||
@@ -50,13 +51,13 @@
|
|||||||
"downloadSelected": "Scarica selezionati"
|
"downloadSelected": "Scarica selezionati"
|
||||||
},
|
},
|
||||||
"upload": {
|
"upload": {
|
||||||
"abortUpload": "Are you sure you wish to abort?"
|
"abortUpload": "Sei sicuro di voler abortire la procedura?"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"forbidden": "Non hai i permessi per accedere a questo file.",
|
"forbidden": "Non hai i permessi per accedere a questo file.",
|
||||||
"internal": "Qualcosa è andato veramente male.",
|
"internal": "Qualcosa è andato veramente male.",
|
||||||
"notFound": "Questo percorso non può essere raggiunto.",
|
"notFound": "Questo percorso non può essere raggiunto.",
|
||||||
"connection": "The server can't be reached."
|
"connection": "Il server non è raggiungibile"
|
||||||
},
|
},
|
||||||
"files": {
|
"files": {
|
||||||
"body": "Contenuto",
|
"body": "Contenuto",
|
||||||
@@ -74,7 +75,7 @@
|
|||||||
"sortByLastModified": "Ordina per ultima modifica",
|
"sortByLastModified": "Ordina per ultima modifica",
|
||||||
"sortByName": "Ordina per nome",
|
"sortByName": "Ordina per nome",
|
||||||
"sortBySize": "Ordina per dimensione",
|
"sortBySize": "Ordina per dimensione",
|
||||||
"noPreview": "Preview is not available for this file."
|
"noPreview": "L'anteprima non è disponibile per questo file."
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"click": "seleziona un file o una cartella",
|
"click": "seleziona un file o una cartella",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Entra",
|
"submit": "Entra",
|
||||||
"username": "Nome utente",
|
"username": "Nome utente",
|
||||||
"usernameTaken": "Username già usato",
|
"usernameTaken": "Username già usato",
|
||||||
"wrongCredentials": "Credenziali errate"
|
"wrongCredentials": "Credenziali errate",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Permanente",
|
"permanent": "Permanente",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -109,8 +113,8 @@
|
|||||||
"currentlyNavigating": "Attualmente navigando su:",
|
"currentlyNavigating": "Attualmente navigando su:",
|
||||||
"deleteMessageMultiple": "Sei sicuro di voler eliminare {count} file?",
|
"deleteMessageMultiple": "Sei sicuro di voler eliminare {count} file?",
|
||||||
"deleteMessageSingle": "Sei sicuro di voler eliminare questo file/cartella?",
|
"deleteMessageSingle": "Sei sicuro di voler eliminare questo file/cartella?",
|
||||||
"deleteMessageShare": "Are you sure you wish to delete this share({path})?",
|
"deleteMessageShare": "Sei sicuro di voler eliminare questo percorso condiviso ({path})?",
|
||||||
"deleteUser": "Are you sure you want to delete this user?",
|
"deleteUser": "Sei sicuro di voler eliminare questo utente?",
|
||||||
"deleteTitle": "Elimina",
|
"deleteTitle": "Elimina",
|
||||||
"displayName": "Nome visualizzato:",
|
"displayName": "Nome visualizzato:",
|
||||||
"download": "Scarica files",
|
"download": "Scarica files",
|
||||||
@@ -137,11 +141,11 @@
|
|||||||
"show": "Mostra",
|
"show": "Mostra",
|
||||||
"size": "Dimensione",
|
"size": "Dimensione",
|
||||||
"upload": "Carica",
|
"upload": "Carica",
|
||||||
"uploadFiles": "Uploading {files} files...",
|
"uploadFiles": "Inviando {files} file...",
|
||||||
"uploadMessage": "Seleziona un'opzione per il caricamento.",
|
"uploadMessage": "Seleziona un'opzione per il caricamento.",
|
||||||
"optionalPassword": "Optional password",
|
"optionalPassword": "Password opzionale",
|
||||||
"resolution": "Resolution",
|
"resolution": "Risoluzione",
|
||||||
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
|
"discardEditorChanges": "Sei sicuro di voler scartare le modifiche apportate?"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"images": "Immagini",
|
"images": "Immagini",
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Video"
|
"video": "Video"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Amministratore",
|
"administrator": "Amministratore",
|
||||||
"allowCommands": "Esegui comandi",
|
"allowCommands": "Esegui comandi",
|
||||||
@@ -170,14 +175,14 @@
|
|||||||
"commandRunnerHelp": "Qui puoi impostare i comandi da eseguire negli eventi nominati. Ne devi scrivere uno per riga. Le variabili d'ambiente {0} e {1} sono disponibili, essendo {0} relativo a {1}. Per altre informazioni su questa funzionalità e sulle variabili d'ambiente utilizzabili, leggi la {2}.",
|
"commandRunnerHelp": "Qui puoi impostare i comandi da eseguire negli eventi nominati. Ne devi scrivere uno per riga. Le variabili d'ambiente {0} e {1} sono disponibili, essendo {0} relativo a {1}. Per altre informazioni su questa funzionalità e sulle variabili d'ambiente utilizzabili, leggi la {2}.",
|
||||||
"commandsUpdated": "Comandi aggiornati!",
|
"commandsUpdated": "Comandi aggiornati!",
|
||||||
"createUserDir": "Crea automaticamente la home directory dell'utente quando lo aggiungi",
|
"createUserDir": "Crea automaticamente la home directory dell'utente quando lo aggiungi",
|
||||||
"minimumPasswordLength": "Minimum password length",
|
"minimumPasswordLength": "Lunghezza minima della password",
|
||||||
"tusUploads": "Chunked Uploads",
|
"tusUploads": "Tranci di invii",
|
||||||
"tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.",
|
"tusUploadsHelp": "File Browser supporta tranci di invii fornendo così la possibilità di inviare efficientemente i file anche su reti instabili.",
|
||||||
"tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.",
|
"tusUploadsChunkSize": "Indica la dimensione massima di una richiesta (invii diretti saranno usati per piccoli invii). Puoi inserire un numero intero per indicare la dimensione in byte, oppure una stringa con l'unità di misura come in 10MB, 1GB, etc.",
|
||||||
"tusUploadsRetryCount": "Number of retries to perform if a chunk fails to upload.",
|
"tusUploadsRetryCount": "Numero di tentativi da effettuare se un trancio di file fallisce.",
|
||||||
"userHomeBasePath": "Base path for user home directories",
|
"userHomeBasePath": "Percorso base per le cartelle utente",
|
||||||
"userScopeGenerationPlaceholder": "The scope will be auto generated",
|
"userScopeGenerationPlaceholder": "La portata verrà autogenerata",
|
||||||
"createUserHomeDirectory": "Create user home directory",
|
"createUserHomeDirectory": "Crea cartella utente",
|
||||||
"customStylesheet": "Foglio di stile personalizzato",
|
"customStylesheet": "Foglio di stile personalizzato",
|
||||||
"defaultUserDescription": "Queste sono le impostazioni predefinite per i nuovi utenti.",
|
"defaultUserDescription": "Queste sono le impostazioni predefinite per i nuovi utenti.",
|
||||||
"disableExternalLinks": "Disabilita link esterni (tranne per la documentazione)",
|
"disableExternalLinks": "Disabilita link esterni (tranne per la documentazione)",
|
||||||
@@ -217,14 +222,14 @@
|
|||||||
"rules": "Regole",
|
"rules": "Regole",
|
||||||
"rulesHelp": "Qui è possibile definire una serie di regole e permessi per questo specifico utente. I file bloccati non appariranno negli elenchi e non saranno accessibili dagli utenti. all'utente. Sia regex che i percorsi relativi all'ambito di applicazione degli utenti sono supportati.\n",
|
"rulesHelp": "Qui è possibile definire una serie di regole e permessi per questo specifico utente. I file bloccati non appariranno negli elenchi e non saranno accessibili dagli utenti. all'utente. Sia regex che i percorsi relativi all'ambito di applicazione degli utenti sono supportati.\n",
|
||||||
"scope": "Scope",
|
"scope": "Scope",
|
||||||
"setDateFormat": "Set exact date format",
|
"setDateFormat": "Fissa il formato di data esatto",
|
||||||
"settingsUpdated": "Impostazioni aggiornate!",
|
"settingsUpdated": "Impostazioni aggiornate!",
|
||||||
"shareDuration": "Durata della condivisione",
|
"shareDuration": "Durata della condivisione",
|
||||||
"shareManagement": "Gestione delle condivisioni",
|
"shareManagement": "Gestione delle condivisioni",
|
||||||
"shareDeleted": "Share deleted!",
|
"shareDeleted": "Percorso condiviso eliminato!",
|
||||||
"singleClick": "Usa un singolo click per aprire file e cartelle",
|
"singleClick": "Usa un singolo click per aprire file e cartelle",
|
||||||
"themes": {
|
"themes": {
|
||||||
"default": "System default",
|
"default": "Impostazione predefinita del sistema",
|
||||||
"dark": "Scuro",
|
"dark": "Scuro",
|
||||||
"light": "Chiaro",
|
"light": "Chiaro",
|
||||||
"title": "Tema"
|
"title": "Tema"
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "更新",
|
"update": "更新",
|
||||||
"upload": "アップロード",
|
"upload": "アップロード",
|
||||||
"openFile": "ファイルを開く",
|
"openFile": "ファイルを開く",
|
||||||
"discardChanges": "Discard"
|
"discardChanges": "Discard",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "ファイルのダウンロード",
|
"downloadFile": "ファイルのダウンロード",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "ログイン",
|
"submit": "ログイン",
|
||||||
"username": "ユーザー名",
|
"username": "ユーザー名",
|
||||||
"usernameTaken": "ユーザー名はすでに取得されています",
|
"usernameTaken": "ユーザー名はすでに取得されています",
|
||||||
"wrongCredentials": "ユーザー名またはパスワードが間違っています"
|
"wrongCredentials": "ユーザー名またはパスワードが間違っています",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "永久",
|
"permanent": "永久",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "動画"
|
"video": "動画"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "管理者",
|
"admin": "管理者",
|
||||||
"administrator": "管理者",
|
"administrator": "管理者",
|
||||||
"allowCommands": "コマンドの実行",
|
"allowCommands": "コマンドの実行",
|
||||||
|
|||||||
@@ -3,17 +3,17 @@
|
|||||||
"cancel": "취소",
|
"cancel": "취소",
|
||||||
"clear": "지우기",
|
"clear": "지우기",
|
||||||
"close": "닫기",
|
"close": "닫기",
|
||||||
"continue": "Continue",
|
"continue": "계속",
|
||||||
"copy": "복사",
|
"copy": "복사",
|
||||||
"copyFile": "파일 복사",
|
"copyFile": "파일 복사",
|
||||||
"copyToClipboard": "클립보드 복사",
|
"copyToClipboard": "클립보드 복사",
|
||||||
"copyDownloadLinkToClipboard": "Copy download link to clipboard",
|
"copyDownloadLinkToClipboard": "다운로드 링크 복사",
|
||||||
"create": "생성",
|
"create": "생성",
|
||||||
"delete": "삭제",
|
"delete": "삭제",
|
||||||
"download": "다운로드",
|
"download": "다운로드",
|
||||||
"file": "File",
|
"file": "파일",
|
||||||
"folder": "Folder",
|
"folder": "폴더",
|
||||||
"fullScreen": "Toggle full screen",
|
"fullScreen": "전체 화면 전환",
|
||||||
"hideDotfiles": "숨김파일(dotfile)을 표시 안함",
|
"hideDotfiles": "숨김파일(dotfile)을 표시 안함",
|
||||||
"info": "정보",
|
"info": "정보",
|
||||||
"more": "더보기",
|
"more": "더보기",
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
"ok": "확인",
|
"ok": "확인",
|
||||||
"permalink": "링크 얻기",
|
"permalink": "링크 얻기",
|
||||||
"previous": "이전",
|
"previous": "이전",
|
||||||
"preview": "Preview",
|
"preview": "미리보기",
|
||||||
"publish": "게시",
|
"publish": "게시",
|
||||||
"rename": "이름 바꾸기",
|
"rename": "이름 바꾸기",
|
||||||
"replace": "대체",
|
"replace": "대체",
|
||||||
@@ -36,13 +36,14 @@
|
|||||||
"selectMultiple": "다중 선택",
|
"selectMultiple": "다중 선택",
|
||||||
"share": "공유",
|
"share": "공유",
|
||||||
"shell": "쉘 전환",
|
"shell": "쉘 전환",
|
||||||
"submit": "Submit",
|
"submit": "제출",
|
||||||
"switchView": "보기 전환",
|
"switchView": "보기 전환",
|
||||||
"toggleSidebar": "사이드바 전환",
|
"toggleSidebar": "사이드바 전환",
|
||||||
"update": "업데이트",
|
"update": "업데이트",
|
||||||
"upload": "업로드",
|
"upload": "업로드",
|
||||||
"openFile": "Open file",
|
"openFile": "파일 열기",
|
||||||
"discardChanges": "Discard"
|
"discardChanges": "변경 사항 취소",
|
||||||
|
"saveChanges": "변경사항 저장"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "파일 다운로드",
|
"downloadFile": "파일 다운로드",
|
||||||
@@ -50,13 +51,13 @@
|
|||||||
"downloadSelected": "선택 항목 다운로드"
|
"downloadSelected": "선택 항목 다운로드"
|
||||||
},
|
},
|
||||||
"upload": {
|
"upload": {
|
||||||
"abortUpload": "Are you sure you wish to abort?"
|
"abortUpload": "업로드를 중단하시겠습니까?"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"forbidden": "접근 권한이 없습니다.",
|
"forbidden": "접근 권한이 없습니다.",
|
||||||
"internal": "오류가 발생하였습니다.",
|
"internal": "오류가 발생하였습니다.",
|
||||||
"notFound": "해당 경로를 찾을 수 없습니다.",
|
"notFound": "해당 경로를 찾을 수 없습니다.",
|
||||||
"connection": "The server can't be reached."
|
"connection": "서버에 연결할 수 없습니다."
|
||||||
},
|
},
|
||||||
"files": {
|
"files": {
|
||||||
"body": "본문",
|
"body": "본문",
|
||||||
@@ -74,7 +75,7 @@
|
|||||||
"sortByLastModified": "수정시간순 정렬",
|
"sortByLastModified": "수정시간순 정렬",
|
||||||
"sortByName": "이름순",
|
"sortByName": "이름순",
|
||||||
"sortBySize": "크기순",
|
"sortBySize": "크기순",
|
||||||
"noPreview": "Preview is not available for this file."
|
"noPreview": "미리 보기가 지원되지 않는 파일 유형입니다."
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"click": "파일이나 디렉토리를 선택해주세요.",
|
"click": "파일이나 디렉토리를 선택해주세요.",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "로그인",
|
"submit": "로그인",
|
||||||
"username": "사용자 이름",
|
"username": "사용자 이름",
|
||||||
"usernameTaken": "사용자 이름이 존재합니다",
|
"usernameTaken": "사용자 이름이 존재합니다",
|
||||||
"wrongCredentials": "사용자 이름 또는 비밀번호를 확인하십시오"
|
"wrongCredentials": "사용자 이름 또는 비밀번호를 확인하십시오",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "영구",
|
"permanent": "영구",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -109,8 +113,8 @@
|
|||||||
"currentlyNavigating": "현재 위치:",
|
"currentlyNavigating": "현재 위치:",
|
||||||
"deleteMessageMultiple": "{count} 개의 파일을 삭제하시겠습니까?",
|
"deleteMessageMultiple": "{count} 개의 파일을 삭제하시겠습니까?",
|
||||||
"deleteMessageSingle": "파일 혹은 디렉토리를 삭제하시겠습니까?",
|
"deleteMessageSingle": "파일 혹은 디렉토리를 삭제하시겠습니까?",
|
||||||
"deleteMessageShare": "Are you sure you wish to delete this share({path})?",
|
"deleteMessageShare": "이 공유({path})를 삭제하시겠습니까?",
|
||||||
"deleteUser": "Are you sure you want to delete this user?",
|
"deleteUser": "이 계정을 삭제하시겠습니까?",
|
||||||
"deleteTitle": "파일 삭제",
|
"deleteTitle": "파일 삭제",
|
||||||
"displayName": "게시 이름:",
|
"displayName": "게시 이름:",
|
||||||
"download": "파일 다운로드",
|
"download": "파일 다운로드",
|
||||||
@@ -137,11 +141,11 @@
|
|||||||
"show": "보기",
|
"show": "보기",
|
||||||
"size": "크기",
|
"size": "크기",
|
||||||
"upload": "업로드",
|
"upload": "업로드",
|
||||||
"uploadFiles": "Uploading {files} files...",
|
"uploadFiles": "{files}개의 파일 업로드 중...",
|
||||||
"uploadMessage": "업로드 옵션을 선택하세요.",
|
"uploadMessage": "업로드 옵션을 선택하세요.",
|
||||||
"optionalPassword": "Optional password",
|
"optionalPassword": "비밀번호 (선택)",
|
||||||
"resolution": "Resolution",
|
"resolution": "해상도",
|
||||||
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
|
"discardEditorChanges": "변경 사항을 취소하시겠습니까?"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"images": "이미지",
|
"images": "이미지",
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "비디오"
|
"video": "비디오"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "관리자",
|
"admin": "관리자",
|
||||||
"administrator": "관리자",
|
"administrator": "관리자",
|
||||||
"allowCommands": "명령 실행",
|
"allowCommands": "명령 실행",
|
||||||
@@ -170,14 +175,14 @@
|
|||||||
"commandRunnerHelp": "이벤트에 해당하는 명령을 설정하세요. 줄당 1개의 명령을 적으세요. 환경 변수{0} 와 {1}이 사용가능하며, {0} 은 {1}에 상대 경로 입니다. 자세한 사항은 {2} 를 참조하세요.",
|
"commandRunnerHelp": "이벤트에 해당하는 명령을 설정하세요. 줄당 1개의 명령을 적으세요. 환경 변수{0} 와 {1}이 사용가능하며, {0} 은 {1}에 상대 경로 입니다. 자세한 사항은 {2} 를 참조하세요.",
|
||||||
"commandsUpdated": "명령 수정됨!",
|
"commandsUpdated": "명령 수정됨!",
|
||||||
"createUserDir": "Auto create user home dir while adding new user",
|
"createUserDir": "Auto create user home dir while adding new user",
|
||||||
"minimumPasswordLength": "Minimum password length",
|
"minimumPasswordLength": "최소 비밀번호 길이",
|
||||||
"tusUploads": "Chunked Uploads",
|
"tusUploads": "분할 업로드",
|
||||||
"tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.",
|
"tusUploadsHelp": "File Browser는 불안정한 네트워크에서도 효율적이고 신뢰성 있는 분할 업로드를 지원합니다.",
|
||||||
"tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.",
|
"tusUploadsChunkSize": "업로드 요청의 최대 크기 (예: 10MB, 1GB)",
|
||||||
"tusUploadsRetryCount": "Number of retries to perform if a chunk fails to upload.",
|
"tusUploadsRetryCount": "업로드 실패 시 재시도 횟수",
|
||||||
"userHomeBasePath": "Base path for user home directories",
|
"userHomeBasePath": "사용자 홈 폴더 기본 경로",
|
||||||
"userScopeGenerationPlaceholder": "The scope will be auto generated",
|
"userScopeGenerationPlaceholder": "범위는 자동으로 생성됩니다.",
|
||||||
"createUserHomeDirectory": "Create user home directory",
|
"createUserHomeDirectory": "사용자 홈 폴더 생성",
|
||||||
"customStylesheet": "커스텀 스타일시트",
|
"customStylesheet": "커스텀 스타일시트",
|
||||||
"defaultUserDescription": "아래 사항은 신규 사용자들에 대한 기본 설정입니다.",
|
"defaultUserDescription": "아래 사항은 신규 사용자들에 대한 기본 설정입니다.",
|
||||||
"disableExternalLinks": "외부 링크 감추기",
|
"disableExternalLinks": "외부 링크 감추기",
|
||||||
@@ -217,14 +222,14 @@
|
|||||||
"rules": "룰",
|
"rules": "룰",
|
||||||
"rulesHelp": "사용자별로 규칙을 허용/방지를 지정할 수 있습니다. 방지된 파일은 보이지 않고 사용자들은 접근할 수 없습니다. 사용자의 접근 허용 범위와 관련해 정규표현식(regex)과 경로를 지원합니다.\n",
|
"rulesHelp": "사용자별로 규칙을 허용/방지를 지정할 수 있습니다. 방지된 파일은 보이지 않고 사용자들은 접근할 수 없습니다. 사용자의 접근 허용 범위와 관련해 정규표현식(regex)과 경로를 지원합니다.\n",
|
||||||
"scope": "범위",
|
"scope": "범위",
|
||||||
"setDateFormat": "Set exact date format",
|
"setDateFormat": "날짜 형식 설정",
|
||||||
"settingsUpdated": "설정 수정됨!",
|
"settingsUpdated": "설정 수정됨!",
|
||||||
"shareDuration": "공유 기간",
|
"shareDuration": "공유 기간",
|
||||||
"shareManagement": "공유 내역 관리",
|
"shareManagement": "공유 내역 관리",
|
||||||
"shareDeleted": "Share deleted!",
|
"shareDeleted": "공유 삭제됨!",
|
||||||
"singleClick": "한번 클릭으로 파일과 폴더를 열도록 합니다.",
|
"singleClick": "한번 클릭으로 파일과 폴더를 열도록 합니다.",
|
||||||
"themes": {
|
"themes": {
|
||||||
"default": "System default",
|
"default": "시스템 기본값",
|
||||||
"dark": "다크테마",
|
"dark": "다크테마",
|
||||||
"light": "라이트테마",
|
"light": "라이트테마",
|
||||||
"title": "테마"
|
"title": "테마"
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Updaten",
|
"update": "Updaten",
|
||||||
"upload": "Uploaden",
|
"upload": "Uploaden",
|
||||||
"openFile": "Open file",
|
"openFile": "Open file",
|
||||||
"discardChanges": "Discard"
|
"discardChanges": "Discard",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Bestand downloaden",
|
"downloadFile": "Bestand downloaden",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Log in",
|
"submit": "Log in",
|
||||||
"username": "Gebruikersnaam",
|
"username": "Gebruikersnaam",
|
||||||
"usernameTaken": "Gebruikersnaam reeds in gebruik",
|
"usernameTaken": "Gebruikersnaam reeds in gebruik",
|
||||||
"wrongCredentials": "Verkeerde inloggegevens"
|
"wrongCredentials": "Verkeerde inloggegevens",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Permanent",
|
"permanent": "Permanent",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Video"
|
"video": "Video"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrator",
|
"administrator": "Administrator",
|
||||||
"allowCommands": "Commando's uitvoeren",
|
"allowCommands": "Commando's uitvoeren",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Opptater",
|
"update": "Opptater",
|
||||||
"upload": "Last opp",
|
"upload": "Last opp",
|
||||||
"openFile": "Open file",
|
"openFile": "Open file",
|
||||||
"discardChanges": "Slett"
|
"discardChanges": "Slett",
|
||||||
|
"saveChanges": "Lagre Endringane "
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Nedlast filen",
|
"downloadFile": "Nedlast filen",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Logg inn",
|
"submit": "Logg inn",
|
||||||
"username": "Brukernavn",
|
"username": "Brukernavn",
|
||||||
"usernameTaken": "Brukernavn er allerede i bruk",
|
"usernameTaken": "Brukernavn er allerede i bruk",
|
||||||
"wrongCredentials": "Feil legitimasjon"
|
"wrongCredentials": "Feil legitimasjon",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "Du har blitt logget ut på grunn av inaktivitet"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Permanent",
|
"permanent": "Permanent",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Video"
|
"video": "Video"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrator",
|
"administrator": "Administrator",
|
||||||
"allowCommands": "Utfør kommandoer",
|
"allowCommands": "Utfør kommandoer",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Aktualizuj",
|
"update": "Aktualizuj",
|
||||||
"upload": "Wyślij",
|
"upload": "Wyślij",
|
||||||
"openFile": "Otwórz plik",
|
"openFile": "Otwórz plik",
|
||||||
"discardChanges": "Odrzuć"
|
"discardChanges": "Odrzuć",
|
||||||
|
"saveChanges": "Zapisz zmiany"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Pobierz plik",
|
"downloadFile": "Pobierz plik",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Zaloguj",
|
"submit": "Zaloguj",
|
||||||
"username": "Nazwa użytkownika",
|
"username": "Nazwa użytkownika",
|
||||||
"usernameTaken": "Ta nazwa użytkownika jest zajęta",
|
"usernameTaken": "Ta nazwa użytkownika jest zajęta",
|
||||||
"wrongCredentials": "Błędne dane logowania"
|
"wrongCredentials": "Błędne dane logowania",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "Wylogowano z powodu braku aktywności."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Permanentny",
|
"permanent": "Permanentny",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Wideo"
|
"video": "Wideo"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Motyw edytora Ace",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrator",
|
"administrator": "Administrator",
|
||||||
"allowCommands": "Wykonaj polecenie",
|
"allowCommands": "Wykonaj polecenie",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Atualizar",
|
"update": "Atualizar",
|
||||||
"upload": "Enviar",
|
"upload": "Enviar",
|
||||||
"openFile": "Abrir",
|
"openFile": "Abrir",
|
||||||
"discardChanges": "Discard"
|
"discardChanges": "Discard",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Baixar arquivo",
|
"downloadFile": "Baixar arquivo",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Login",
|
"submit": "Login",
|
||||||
"username": "Nome do usuário",
|
"username": "Nome do usuário",
|
||||||
"usernameTaken": "Nome de usuário já existe",
|
"usernameTaken": "Nome de usuário já existe",
|
||||||
"wrongCredentials": "Ops! Dados incorretos."
|
"wrongCredentials": "Ops! Dados incorretos.",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Permanente",
|
"permanent": "Permanente",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Vídeos"
|
"video": "Vídeos"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrador",
|
"administrator": "Administrador",
|
||||||
"allowCommands": "Executar comandos",
|
"allowCommands": "Executar comandos",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Atualizar",
|
"update": "Atualizar",
|
||||||
"upload": "Enviar",
|
"upload": "Enviar",
|
||||||
"openFile": "Open file",
|
"openFile": "Open file",
|
||||||
"discardChanges": "Discard"
|
"discardChanges": "Discard",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Descarregar ficheiro",
|
"downloadFile": "Descarregar ficheiro",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Entrar na conta",
|
"submit": "Entrar na conta",
|
||||||
"username": "Nome de utilizador",
|
"username": "Nome de utilizador",
|
||||||
"usernameTaken": "O nome de utilizador já está registado",
|
"usernameTaken": "O nome de utilizador já está registado",
|
||||||
"wrongCredentials": "Dados errados"
|
"wrongCredentials": "Dados errados",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Permanente",
|
"permanent": "Permanente",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Vídeos"
|
"video": "Vídeos"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrador",
|
"administrator": "Administrador",
|
||||||
"allowCommands": "Executar comandos",
|
"allowCommands": "Executar comandos",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Actualizează",
|
"update": "Actualizează",
|
||||||
"upload": "Încarcă",
|
"upload": "Încarcă",
|
||||||
"openFile": "Open file",
|
"openFile": "Open file",
|
||||||
"discardChanges": "Discard"
|
"discardChanges": "Discard",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Descarcă fișier",
|
"downloadFile": "Descarcă fișier",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Autentificare",
|
"submit": "Autentificare",
|
||||||
"username": "Utilizator",
|
"username": "Utilizator",
|
||||||
"usernameTaken": "Utilizatorul există",
|
"usernameTaken": "Utilizatorul există",
|
||||||
"wrongCredentials": "Informații greșite"
|
"wrongCredentials": "Informații greșite",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Permanent",
|
"permanent": "Permanent",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Video"
|
"video": "Video"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrator",
|
"administrator": "Administrator",
|
||||||
"allowCommands": "Execută comenzi",
|
"allowCommands": "Execută comenzi",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Обновить",
|
"update": "Обновить",
|
||||||
"upload": "Загрузить",
|
"upload": "Загрузить",
|
||||||
"openFile": "Открыть файл",
|
"openFile": "Открыть файл",
|
||||||
"discardChanges": "Отказаться"
|
"discardChanges": "Отказаться",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Скачать файл",
|
"downloadFile": "Скачать файл",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Войти",
|
"submit": "Войти",
|
||||||
"username": "Имя пользователя",
|
"username": "Имя пользователя",
|
||||||
"usernameTaken": "Данное имя пользователя уже занято",
|
"usernameTaken": "Данное имя пользователя уже занято",
|
||||||
"wrongCredentials": "Неверные данные"
|
"wrongCredentials": "Неверные данные",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Постоянный",
|
"permanent": "Постоянный",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Видео"
|
"video": "Видео"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Админ",
|
"admin": "Админ",
|
||||||
"administrator": "Администратор",
|
"administrator": "Администратор",
|
||||||
"allowCommands": "Запуск команд",
|
"allowCommands": "Запуск команд",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Aktualizovať",
|
"update": "Aktualizovať",
|
||||||
"upload": "Nahrať",
|
"upload": "Nahrať",
|
||||||
"openFile": "Otvoriť súbor",
|
"openFile": "Otvoriť súbor",
|
||||||
"discardChanges": "Zahodiť"
|
"discardChanges": "Zahodiť",
|
||||||
|
"saveChanges": "Uložiť zmeny"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Stiahnuť súbor",
|
"downloadFile": "Stiahnuť súbor",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Prihlásiť",
|
"submit": "Prihlásiť",
|
||||||
"username": "Používateľské meno",
|
"username": "Používateľské meno",
|
||||||
"usernameTaken": "Meno je už obsadené",
|
"usernameTaken": "Meno je už obsadené",
|
||||||
"wrongCredentials": "Nesprávne prihlasovacie údaje"
|
"wrongCredentials": "Nesprávne prihlasovacie údaje",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "Boli ste odhlásení z dôvodu nečinnosti."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Trvalé",
|
"permanent": "Trvalé",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Video"
|
"video": "Video"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administrátor",
|
"administrator": "Administrátor",
|
||||||
"allowCommands": "Vykonávať príkazy",
|
"allowCommands": "Vykonávať príkazy",
|
||||||
|
|||||||
@@ -3,18 +3,18 @@
|
|||||||
"cancel": "Avbryt",
|
"cancel": "Avbryt",
|
||||||
"clear": "Rensa",
|
"clear": "Rensa",
|
||||||
"close": "Stäng",
|
"close": "Stäng",
|
||||||
"continue": "Continue",
|
"continue": "Fortsätt",
|
||||||
"copy": "Kopiera",
|
"copy": "Kopiera",
|
||||||
"copyFile": "Kopiera fil",
|
"copyFile": "Kopiera fil",
|
||||||
"copyToClipboard": "Kopiera till urklipp",
|
"copyToClipboard": "Kopiera till urklipp",
|
||||||
"copyDownloadLinkToClipboard": "Copy download link to clipboard",
|
"copyDownloadLinkToClipboard": "Kopiera hämtningslänk till urklipp",
|
||||||
"create": "Skapa",
|
"create": "Skapa",
|
||||||
"delete": "Ta bort",
|
"delete": "Ta bort",
|
||||||
"download": "Ladda ner",
|
"download": "Ladda ner",
|
||||||
"file": "File",
|
"file": "Fil",
|
||||||
"folder": "Folder",
|
"folder": "Mapp",
|
||||||
"fullScreen": "Toggle full screen",
|
"fullScreen": "Växla helskärm",
|
||||||
"hideDotfiles": "Hide dotfiles",
|
"hideDotfiles": "Dölj punktfiler",
|
||||||
"info": "Info",
|
"info": "Info",
|
||||||
"more": "Mer",
|
"more": "Mer",
|
||||||
"move": "Flytta",
|
"move": "Flytta",
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
"ok": "OK",
|
"ok": "OK",
|
||||||
"permalink": "Skapa en permanent länk",
|
"permalink": "Skapa en permanent länk",
|
||||||
"previous": "Föregående",
|
"previous": "Föregående",
|
||||||
"preview": "Preview",
|
"preview": "Förhandsvisa",
|
||||||
"publish": "Publisera",
|
"publish": "Publisera",
|
||||||
"rename": "Ändra namn",
|
"rename": "Ändra namn",
|
||||||
"replace": "Ersätt",
|
"replace": "Ersätt",
|
||||||
@@ -36,27 +36,28 @@
|
|||||||
"selectMultiple": "Välj flera",
|
"selectMultiple": "Välj flera",
|
||||||
"share": "Dela",
|
"share": "Dela",
|
||||||
"shell": "Växla skal",
|
"shell": "Växla skal",
|
||||||
"submit": "Submit",
|
"submit": "Skicka",
|
||||||
"switchView": "Byt vy",
|
"switchView": "Byt vy",
|
||||||
"toggleSidebar": "Växla sidofält",
|
"toggleSidebar": "Växla sidofält",
|
||||||
"update": "Uppdatera",
|
"update": "Uppdatera",
|
||||||
"upload": "Ladda upp",
|
"upload": "Ladda upp",
|
||||||
"openFile": "Open file",
|
"openFile": "Öppna fil",
|
||||||
"discardChanges": "Discard"
|
"discardChanges": "Förkasta",
|
||||||
|
"saveChanges": "Spara ändringar"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Ladda ner fil",
|
"downloadFile": "Ladda ner fil",
|
||||||
"downloadFolder": "Ladda ner mapp",
|
"downloadFolder": "Ladda ner mapp",
|
||||||
"downloadSelected": "Download Selected"
|
"downloadSelected": "Hämta markerade"
|
||||||
},
|
},
|
||||||
"upload": {
|
"upload": {
|
||||||
"abortUpload": "Are you sure you wish to abort?"
|
"abortUpload": "Är du säker på att du vill avbryta?"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"forbidden": "Du saknar rättigheter till detta",
|
"forbidden": "Du saknar rättigheter till detta",
|
||||||
"internal": "Något gick fel",
|
"internal": "Något gick fel",
|
||||||
"notFound": "Det går inte att nå den här platsen.",
|
"notFound": "Det går inte att nå den här platsen.",
|
||||||
"connection": "The server can't be reached."
|
"connection": "Servern går inte att nå."
|
||||||
},
|
},
|
||||||
"files": {
|
"files": {
|
||||||
"body": "Huvud",
|
"body": "Huvud",
|
||||||
@@ -74,7 +75,7 @@
|
|||||||
"sortByLastModified": "Sortera på senast ändrad",
|
"sortByLastModified": "Sortera på senast ändrad",
|
||||||
"sortByName": "Sortera på namn",
|
"sortByName": "Sortera på namn",
|
||||||
"sortBySize": "Sortera på storlek",
|
"sortBySize": "Sortera på storlek",
|
||||||
"noPreview": "Preview is not available for this file."
|
"noPreview": "Förhandsvisning är inte tillgänglig för denna fil."
|
||||||
},
|
},
|
||||||
"help": {
|
"help": {
|
||||||
"click": "välj fil eller mapp",
|
"click": "välj fil eller mapp",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Logga in",
|
"submit": "Logga in",
|
||||||
"username": "Användarnamn",
|
"username": "Användarnamn",
|
||||||
"usernameTaken": "Användarnamn upptaget",
|
"usernameTaken": "Användarnamn upptaget",
|
||||||
"wrongCredentials": "Fel inloggning"
|
"wrongCredentials": "Fel inloggning",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "Du har blivit utloggad på grund av inaktivitet."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Permanent",
|
"permanent": "Permanent",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -109,8 +113,8 @@
|
|||||||
"currentlyNavigating": "För närvarande navigerar du på:",
|
"currentlyNavigating": "För närvarande navigerar du på:",
|
||||||
"deleteMessageMultiple": "Är du säker på att du vill radera {count} filer(na)?",
|
"deleteMessageMultiple": "Är du säker på att du vill radera {count} filer(na)?",
|
||||||
"deleteMessageSingle": "Är du säker på att du vill radera denna fil/mapp",
|
"deleteMessageSingle": "Är du säker på att du vill radera denna fil/mapp",
|
||||||
"deleteMessageShare": "Are you sure you wish to delete this share({path})?",
|
"deleteMessageShare": "Är du säker på att du vill ta bort denna utdelning({path})?",
|
||||||
"deleteUser": "Are you sure you want to delete this user?",
|
"deleteUser": "Är du säker på att du vill ta bort denna användare?",
|
||||||
"deleteTitle": "Ta bort filer",
|
"deleteTitle": "Ta bort filer",
|
||||||
"displayName": "Visningsnamn:",
|
"displayName": "Visningsnamn:",
|
||||||
"download": "Ladda ner filer",
|
"download": "Ladda ner filer",
|
||||||
@@ -136,12 +140,12 @@
|
|||||||
"scheduleMessage": "Pick a date and time to schedule the publication of this post.",
|
"scheduleMessage": "Pick a date and time to schedule the publication of this post.",
|
||||||
"show": "Visa",
|
"show": "Visa",
|
||||||
"size": "Storlek",
|
"size": "Storlek",
|
||||||
"upload": "Upload",
|
"upload": "Ladda upp",
|
||||||
"uploadFiles": "Uploading {files} files...",
|
"uploadFiles": "Laddar upp {files} filer...",
|
||||||
"uploadMessage": "Select an option to upload.",
|
"uploadMessage": "Välj ett alternativ att ladda upp.",
|
||||||
"optionalPassword": "Optional password",
|
"optionalPassword": "Valfritt lösenord",
|
||||||
"resolution": "Resolution",
|
"resolution": "Upplösning",
|
||||||
"discardEditorChanges": "Are you sure you wish to discard the changes you've made?"
|
"discardEditorChanges": "Är du säker på att du vill förkasta ändringarna du gjort?"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"images": "Bilder",
|
"images": "Bilder",
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Video"
|
"video": "Video"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Tema för Ace editor",
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"administrator": "Administratör",
|
"administrator": "Administratör",
|
||||||
"allowCommands": "Exekvera kommandon",
|
"allowCommands": "Exekvera kommandon",
|
||||||
@@ -170,14 +175,14 @@
|
|||||||
"commandRunnerHelp": "Här kan du ange kommandon som körs i de namngivna händelserna. Du måste skriva en per rad. Miljövariablerna {0} och {1} kommer att vara tillgängliga, och vara {0} i förhållande till {1}. För mer information om den här funktionen och de tillgängliga miljövariablerna, vänligen läs {2}.",
|
"commandRunnerHelp": "Här kan du ange kommandon som körs i de namngivna händelserna. Du måste skriva en per rad. Miljövariablerna {0} och {1} kommer att vara tillgängliga, och vara {0} i förhållande till {1}. För mer information om den här funktionen och de tillgängliga miljövariablerna, vänligen läs {2}.",
|
||||||
"commandsUpdated": "Kommandon uppdaterade!",
|
"commandsUpdated": "Kommandon uppdaterade!",
|
||||||
"createUserDir": "Auto skapa användarens hemkatalog när du lägger till nya användare",
|
"createUserDir": "Auto skapa användarens hemkatalog när du lägger till nya användare",
|
||||||
"minimumPasswordLength": "Minimum password length",
|
"minimumPasswordLength": "Minsta lösenordslängd",
|
||||||
"tusUploads": "Chunked Uploads",
|
"tusUploads": "Uppdelade uppladdningar",
|
||||||
"tusUploadsHelp": "File Browser supports chunked file uploads, allowing for the creation of efficient, reliable, resumable and chunked file uploads even on unreliable networks.",
|
"tusUploadsHelp": "Filbläddraren stöder uppdelade filuppladdningar, vilket möjliggör effektiva, tillförlitliga, återupptagbara och uppdelade filuppladdningar även på otillförlitliga nätverk.",
|
||||||
"tusUploadsChunkSize": "Indicates to maximum size of a request (direct uploads will be used for smaller uploads). You may input a plain integer denoting byte size input or a string like 10MB, 1GB etc.",
|
"tusUploadsChunkSize": "Anger maximal storlek för en begäran (direkta uppladdningar används för mindre uppladdningar). Du kan ange ett helt tal som anger storleken i byte eller en sträng som 10 MB, 1 GB osv.",
|
||||||
"tusUploadsRetryCount": "Number of retries to perform if a chunk fails to upload.",
|
"tusUploadsRetryCount": "Antal försök som ska göras om en del inte kan laddas upp.",
|
||||||
"userHomeBasePath": "Base path for user home directories",
|
"userHomeBasePath": "Bassökväg för användarnas hemkataloger",
|
||||||
"userScopeGenerationPlaceholder": "The scope will be auto generated",
|
"userScopeGenerationPlaceholder": "Omfånget kommer att automatiskt genereras",
|
||||||
"createUserHomeDirectory": "Create user home directory",
|
"createUserHomeDirectory": "Skapa användarens hemkatalog",
|
||||||
"customStylesheet": "Anpassad formatmall",
|
"customStylesheet": "Anpassad formatmall",
|
||||||
"defaultUserDescription": "Detta är standard inställningar för användare.",
|
"defaultUserDescription": "Detta är standard inställningar för användare.",
|
||||||
"disableExternalLinks": "Inaktivera externa länkar (förutom dokumentation)",
|
"disableExternalLinks": "Inaktivera externa länkar (förutom dokumentation)",
|
||||||
@@ -188,7 +193,7 @@
|
|||||||
"executeOnShellDescription": "Som standard kör fil bläddraren kommandona genom att anropa deras binärfiler direkt. Om du vill köra dem på ett skal i stället (till exempel bash eller PowerShell), kan du definiera det här med nödvändiga argument och flaggor. Om det är inställt kommer kommandot du kör att läggas till som ett argument. Detta gäller både användar kommandon och händelse krokar.",
|
"executeOnShellDescription": "Som standard kör fil bläddraren kommandona genom att anropa deras binärfiler direkt. Om du vill köra dem på ett skal i stället (till exempel bash eller PowerShell), kan du definiera det här med nödvändiga argument och flaggor. Om det är inställt kommer kommandot du kör att läggas till som ett argument. Detta gäller både användar kommandon och händelse krokar.",
|
||||||
"globalRules": "Det här är en global uppsättning regler för att tillåta och inte tillåta. De gäller för alla användare. Du kan definiera specifika regler för varje användares inställningar för att åsidosätta de här inställningarna.",
|
"globalRules": "Det här är en global uppsättning regler för att tillåta och inte tillåta. De gäller för alla användare. Du kan definiera specifika regler för varje användares inställningar för att åsidosätta de här inställningarna.",
|
||||||
"globalSettings": "Globala inställningar",
|
"globalSettings": "Globala inställningar",
|
||||||
"hideDotfiles": "Hide dotfiles",
|
"hideDotfiles": "Dölj punktfiler",
|
||||||
"insertPath": "Ange sökväg",
|
"insertPath": "Ange sökväg",
|
||||||
"insertRegex": "Sätt in regex expression",
|
"insertRegex": "Sätt in regex expression",
|
||||||
"instanceName": "Instans namn",
|
"instanceName": "Instans namn",
|
||||||
@@ -199,7 +204,7 @@
|
|||||||
"newUser": "Ny användare",
|
"newUser": "Ny användare",
|
||||||
"password": "Lösenord",
|
"password": "Lösenord",
|
||||||
"passwordUpdated": "Lösenord uppdaterat",
|
"passwordUpdated": "Lösenord uppdaterat",
|
||||||
"path": "Path",
|
"path": "Sökväg",
|
||||||
"perm": {
|
"perm": {
|
||||||
"create": "Skapa filer och mappar",
|
"create": "Skapa filer och mappar",
|
||||||
"delete": "Ta bort filer och mappar",
|
"delete": "Ta bort filer och mappar",
|
||||||
@@ -217,17 +222,17 @@
|
|||||||
"rules": "Regler",
|
"rules": "Regler",
|
||||||
"rulesHelp": "Här kan du definiera en uppsättning regler för godkänna och neka för den här specifika användaren. Den blockerade filen kommer inte upp i listningarna och kommer inte att vara tillgänglig till användaren. Vi stöder regex och sökvägar i förhållande till användarnas omfång.\n",
|
"rulesHelp": "Här kan du definiera en uppsättning regler för godkänna och neka för den här specifika användaren. Den blockerade filen kommer inte upp i listningarna och kommer inte att vara tillgänglig till användaren. Vi stöder regex och sökvägar i förhållande till användarnas omfång.\n",
|
||||||
"scope": "Omfattning",
|
"scope": "Omfattning",
|
||||||
"setDateFormat": "Set exact date format",
|
"setDateFormat": "Ställ in exakt datumformat",
|
||||||
"settingsUpdated": "Inställning uppdaterad!",
|
"settingsUpdated": "Inställning uppdaterad!",
|
||||||
"shareDuration": "Share Duration",
|
"shareDuration": "Utdelningstid",
|
||||||
"shareManagement": "Share Management",
|
"shareManagement": "Utdelningshantering",
|
||||||
"shareDeleted": "Share deleted!",
|
"shareDeleted": "Utdelning borttagen!",
|
||||||
"singleClick": "Use single clicks to open files and directories",
|
"singleClick": "Använd enkla klick för att öppna filer och kataloger",
|
||||||
"themes": {
|
"themes": {
|
||||||
"default": "System default",
|
"default": "Systemet standard",
|
||||||
"dark": "Dark",
|
"dark": "Mörk",
|
||||||
"light": "Light",
|
"light": "Ljus",
|
||||||
"title": "Theme"
|
"title": "Tema"
|
||||||
},
|
},
|
||||||
"user": "Användare",
|
"user": "Användare",
|
||||||
"userCommands": "Kommandon",
|
"userCommands": "Kommandon",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Güncelle",
|
"update": "Güncelle",
|
||||||
"upload": "Yükle",
|
"upload": "Yükle",
|
||||||
"openFile": "Dosyayı aç",
|
"openFile": "Dosyayı aç",
|
||||||
"discardChanges": "Discard"
|
"discardChanges": "Discard",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Dosyayı indir",
|
"downloadFile": "Dosyayı indir",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Giriş",
|
"submit": "Giriş",
|
||||||
"username": "Kullanıcı adı",
|
"username": "Kullanıcı adı",
|
||||||
"usernameTaken": "Kullanıcı adı mevcut",
|
"usernameTaken": "Kullanıcı adı mevcut",
|
||||||
"wrongCredentials": "Yanlış hesap bilgileri"
|
"wrongCredentials": "Yanlış hesap bilgileri",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Kalıcı",
|
"permanent": "Kalıcı",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Video"
|
"video": "Video"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Yönetim",
|
"admin": "Yönetim",
|
||||||
"administrator": "Yönetici",
|
"administrator": "Yönetici",
|
||||||
"allowCommands": "Komutları çalıştır",
|
"allowCommands": "Komutları çalıştır",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Оновити",
|
"update": "Оновити",
|
||||||
"upload": "Вивантажити",
|
"upload": "Вивантажити",
|
||||||
"openFile": "Відкрити файл",
|
"openFile": "Відкрити файл",
|
||||||
"discardChanges": "Скасувати"
|
"discardChanges": "Скасувати",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Завантажити файл",
|
"downloadFile": "Завантажити файл",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Увійти",
|
"submit": "Увійти",
|
||||||
"username": "Ім'я користувача",
|
"username": "Ім'я користувача",
|
||||||
"usernameTaken": "Ім'я користувача вже використовується",
|
"usernameTaken": "Ім'я користувача вже використовується",
|
||||||
"wrongCredentials": "Неправильне ім'я користувача або пароль"
|
"wrongCredentials": "Неправильне ім'я користувача або пароль",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Постійний",
|
"permanent": "Постійний",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Відео"
|
"video": "Відео"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Адмін",
|
"admin": "Адмін",
|
||||||
"administrator": "Адміністратор",
|
"administrator": "Адміністратор",
|
||||||
"allowCommands": "Запуск команд",
|
"allowCommands": "Запуск команд",
|
||||||
@@ -173,15 +178,15 @@
|
|||||||
"minimumPasswordLength": "Мінімальна довжина паролю",
|
"minimumPasswordLength": "Мінімальна довжина паролю",
|
||||||
"tusUploads": "Фрагментовані завантаження",
|
"tusUploads": "Фрагментовані завантаження",
|
||||||
"tusUploadsHelp": "File Browser підтримує завантаження частинами, дозволяючи створення ефективних, надійних, відновлюваних та фрагментованих завантажень навіть при ненадійному з'єднанні.",
|
"tusUploadsHelp": "File Browser підтримує завантаження частинами, дозволяючи створення ефективних, надійних, відновлюваних та фрагментованих завантажень навіть при ненадійному з'єднанні.",
|
||||||
"tusUploadsChunkSize": "Вказує на максимальний розмір запиту (для менших завантажень використовуватиметься пряме завантаження). Ви можете ввести цілочисельне значення у байтах або ж рядок на кшталт 10MB, 1GB тощо.",
|
"tusUploadsChunkSize": "Максимальний розмір запиту (для менших завантажень використовуватиметься пряме завантаження). Ви можете ввести цілочисельне значення у байтах або ж рядок на кшталт 10MB, 1GB тощо",
|
||||||
"tusUploadsRetryCount": "Кількість повторних спроб які потрібно виконати, якщо фрагмент не вдалося завантажити.",
|
"tusUploadsRetryCount": "Кількість повторних спроб які потрібно виконати, якщо фрагмент не вдалося завантажити",
|
||||||
"userHomeBasePath": "Основний шлях для домашніх каталогів користувачів",
|
"userHomeBasePath": "Основний шлях для домашніх каталогів користувачів",
|
||||||
"userScopeGenerationPlaceholder": "Кореневий каталог буде згенеровано автоматично",
|
"userScopeGenerationPlaceholder": "Кореневий каталог буде згенеровано автоматично",
|
||||||
"createUserHomeDirectory": "Створити домашній каталог користувача",
|
"createUserHomeDirectory": "Створити домашній каталог користувача",
|
||||||
"customStylesheet": "Свій стиль",
|
"customStylesheet": "Свій стиль",
|
||||||
"defaultUserDescription": "Це налаштування за замовчуванням для нових користувачів.",
|
"defaultUserDescription": "Це налаштування за замовчуванням для нових користувачів.",
|
||||||
"disableExternalLinks": "Вимкнути зовнішні посилання (крім документації)",
|
"disableExternalLinks": "Вимкнути зовнішні посилання (крім документації)",
|
||||||
"disableUsedDiskPercentage": "Disable used disk percentage graph",
|
"disableUsedDiskPercentage": "Вимкнути графік використання диску",
|
||||||
"documentation": "документація",
|
"documentation": "документація",
|
||||||
"examples": "Приклади",
|
"examples": "Приклади",
|
||||||
"executeOnShell": "Виконати в командному рядку",
|
"executeOnShell": "Виконати в командному рядку",
|
||||||
@@ -231,7 +236,7 @@
|
|||||||
},
|
},
|
||||||
"user": "Користувач",
|
"user": "Користувач",
|
||||||
"userCommands": "Команди",
|
"userCommands": "Команди",
|
||||||
"userCommandsHelp": "Список команд, доступних користувачу, розділений пробілами. Приклад:\n",
|
"userCommandsHelp": "Список команд, доступних користувачу, розділений пробілами. Наприклад:\n",
|
||||||
"userCreated": "Користувача створено!",
|
"userCreated": "Користувача створено!",
|
||||||
"userDefaults": "Налаштування користувача за замовчуванням",
|
"userDefaults": "Налаштування користувача за замовчуванням",
|
||||||
"userDeleted": "Користувача видалено!",
|
"userDeleted": "Користувача видалено!",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "Cập nhật",
|
"update": "Cập nhật",
|
||||||
"upload": "Tải lên",
|
"upload": "Tải lên",
|
||||||
"openFile": "Mở tệp",
|
"openFile": "Mở tệp",
|
||||||
"discardChanges": "Hủy bỏ thay đổi"
|
"discardChanges": "Hủy bỏ thay đổi",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "Tải xuống tệp tin",
|
"downloadFile": "Tải xuống tệp tin",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "Đăng nhập",
|
"submit": "Đăng nhập",
|
||||||
"username": "Tên người dùng",
|
"username": "Tên người dùng",
|
||||||
"usernameTaken": "Tên người dùng đã tồn tại",
|
"usernameTaken": "Tên người dùng đã tồn tại",
|
||||||
"wrongCredentials": "Thông tin đăng nhập không đúng"
|
"wrongCredentials": "Thông tin đăng nhập không đúng",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "Vĩnh viễn",
|
"permanent": "Vĩnh viễn",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "Video"
|
"video": "Video"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "Quản trị viên",
|
"admin": "Quản trị viên",
|
||||||
"administrator": "Người quản trị",
|
"administrator": "Người quản trị",
|
||||||
"allowCommands": "Thực thi lệnh",
|
"allowCommands": "Thực thi lệnh",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "更新",
|
"update": "更新",
|
||||||
"upload": "上传",
|
"upload": "上传",
|
||||||
"openFile": "打开文件",
|
"openFile": "打开文件",
|
||||||
"discardChanges": "放弃更改"
|
"discardChanges": "放弃更改",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "下载文件",
|
"downloadFile": "下载文件",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "登录",
|
"submit": "登录",
|
||||||
"username": "用户名",
|
"username": "用户名",
|
||||||
"usernameTaken": "用户名已经被使用",
|
"usernameTaken": "用户名已经被使用",
|
||||||
"wrongCredentials": "用户名或密码错误"
|
"wrongCredentials": "用户名或密码错误",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "永久",
|
"permanent": "永久",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "视频"
|
"video": "视频"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "管理员",
|
"admin": "管理员",
|
||||||
"administrator": "管理员",
|
"administrator": "管理员",
|
||||||
"allowCommands": "执行命令(Shell 命令)",
|
"allowCommands": "执行命令(Shell 命令)",
|
||||||
|
|||||||
@@ -42,7 +42,8 @@
|
|||||||
"update": "更新",
|
"update": "更新",
|
||||||
"upload": "上傳",
|
"upload": "上傳",
|
||||||
"openFile": "開啟檔案",
|
"openFile": "開啟檔案",
|
||||||
"discardChanges": "放棄變更"
|
"discardChanges": "放棄變更",
|
||||||
|
"saveChanges": "Save changes"
|
||||||
},
|
},
|
||||||
"download": {
|
"download": {
|
||||||
"downloadFile": "下載檔案",
|
"downloadFile": "下載檔案",
|
||||||
@@ -100,7 +101,10 @@
|
|||||||
"submit": "登入",
|
"submit": "登入",
|
||||||
"username": "帳號",
|
"username": "帳號",
|
||||||
"usernameTaken": "用戶名已存在",
|
"usernameTaken": "用戶名已存在",
|
||||||
"wrongCredentials": "帳號或密碼錯誤"
|
"wrongCredentials": "帳號或密碼錯誤",
|
||||||
|
"logout_reasons": {
|
||||||
|
"inactivity": "You have been logged out due to inactivity."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"permanent": "永久",
|
"permanent": "永久",
|
||||||
"prompts": {
|
"prompts": {
|
||||||
@@ -154,6 +158,7 @@
|
|||||||
"video": "影片"
|
"video": "影片"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
|
"aceEditorTheme": "Ace editor theme",
|
||||||
"admin": "管理員",
|
"admin": "管理員",
|
||||||
"administrator": "管理員",
|
"administrator": "管理員",
|
||||||
"allowCommands": "執行命令",
|
"allowCommands": "執行命令",
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ export const useAuthStore = defineStore("auth", {
|
|||||||
state: (): {
|
state: (): {
|
||||||
user: IUser | null;
|
user: IUser | null;
|
||||||
jwt: string;
|
jwt: string;
|
||||||
|
logoutTimer: number | null;
|
||||||
} => ({
|
} => ({
|
||||||
user: null,
|
user: null,
|
||||||
jwt: "",
|
jwt: "",
|
||||||
|
logoutTimer: null,
|
||||||
}),
|
}),
|
||||||
getters: {
|
getters: {
|
||||||
// user and jwt getter removed, no longer needed
|
// user and jwt getter removed, no longer needed
|
||||||
@@ -37,5 +39,8 @@ export const useAuthStore = defineStore("auth", {
|
|||||||
clearUser() {
|
clearUser() {
|
||||||
this.$reset();
|
this.$reset();
|
||||||
},
|
},
|
||||||
|
setLogoutTimer(logoutTimer: number | null) {
|
||||||
|
this.logoutTimer = logoutTimer;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export const useLayoutStore = defineStore("layout", {
|
|||||||
prompt: value,
|
prompt: value,
|
||||||
confirm: null,
|
confirm: null,
|
||||||
action: undefined,
|
action: undefined,
|
||||||
|
saveAction: undefined,
|
||||||
props: null,
|
props: null,
|
||||||
close: null,
|
close: null,
|
||||||
});
|
});
|
||||||
@@ -51,6 +52,7 @@ export const useLayoutStore = defineStore("layout", {
|
|||||||
prompt: value.prompt,
|
prompt: value.prompt,
|
||||||
confirm: value?.confirm,
|
confirm: value?.confirm,
|
||||||
action: value?.action,
|
action: value?.action,
|
||||||
|
saveAction: value?.saveAction,
|
||||||
props: value?.props,
|
props: value?.props,
|
||||||
close: value?.close,
|
close: value?.close,
|
||||||
});
|
});
|
||||||
|
|||||||
1
frontend/src/types/layout.d.ts
vendored
@@ -2,6 +2,7 @@ interface PopupProps {
|
|||||||
prompt: string;
|
prompt: string;
|
||||||
confirm?: any;
|
confirm?: any;
|
||||||
action?: PopupAction;
|
action?: PopupAction;
|
||||||
|
saveAction?: () => void;
|
||||||
props?: any;
|
props?: any;
|
||||||
close?: (() => Promise<string>) | null;
|
close?: (() => Promise<string>) | null;
|
||||||
}
|
}
|
||||||
|
|||||||
3
frontend/src/types/settings.d.ts
vendored
@@ -17,10 +17,11 @@ interface SettingsDefaults {
|
|||||||
viewMode: ViewModeType;
|
viewMode: ViewModeType;
|
||||||
singleClick: boolean;
|
singleClick: boolean;
|
||||||
sorting: Sorting;
|
sorting: Sorting;
|
||||||
perm: Permissions;
|
perm: UserPermissions;
|
||||||
commands: any[];
|
commands: any[];
|
||||||
hideDotfiles: boolean;
|
hideDotfiles: boolean;
|
||||||
dateFormat: boolean;
|
dateFormat: boolean;
|
||||||
|
aceEditorTheme: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SettingsBranding {
|
interface SettingsBranding {
|
||||||
|
|||||||
27
frontend/src/types/user.d.ts
vendored
@@ -4,7 +4,7 @@ interface IUser {
|
|||||||
password: string;
|
password: string;
|
||||||
scope: string;
|
scope: string;
|
||||||
locale: string;
|
locale: string;
|
||||||
perm: Permissions;
|
perm: UserPermissions;
|
||||||
commands: string[];
|
commands: string[];
|
||||||
rules: IRule[];
|
rules: IRule[];
|
||||||
lockPassword: boolean;
|
lockPassword: boolean;
|
||||||
@@ -13,26 +13,27 @@ interface IUser {
|
|||||||
dateFormat: boolean;
|
dateFormat: boolean;
|
||||||
viewMode: ViewModeType;
|
viewMode: ViewModeType;
|
||||||
sorting?: Sorting;
|
sorting?: Sorting;
|
||||||
|
aceEditorTheme: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type ViewModeType = "list" | "mosaic" | "mosaic gallery";
|
type ViewModeType = "list" | "mosaic" | "mosaic gallery";
|
||||||
|
|
||||||
interface IUserForm {
|
interface IUserForm {
|
||||||
id?: number;
|
id?: number;
|
||||||
username?: string;
|
username: string;
|
||||||
password?: string;
|
password: string;
|
||||||
scope?: string;
|
scope: string;
|
||||||
locale?: string;
|
locale: string;
|
||||||
perm?: Permissions;
|
perm: UserPermissions;
|
||||||
commands?: string[];
|
commands: string[];
|
||||||
rules?: IRule[];
|
rules: IRule[];
|
||||||
lockPassword?: boolean;
|
lockPassword: boolean;
|
||||||
hideDotfiles?: boolean;
|
hideDotfiles: boolean;
|
||||||
singleClick?: boolean;
|
singleClick: boolean;
|
||||||
dateFormat?: boolean;
|
dateFormat: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Permissions {
|
interface UserPermissions {
|
||||||
admin: boolean;
|
admin: boolean;
|
||||||
copy: boolean;
|
copy: boolean;
|
||||||
create: boolean;
|
create: boolean;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { JwtPayload } from "jwt-decode";
|
|||||||
import { jwtDecode } from "jwt-decode";
|
import { jwtDecode } from "jwt-decode";
|
||||||
import { baseURL, noAuth } from "./constants";
|
import { baseURL, noAuth } from "./constants";
|
||||||
import { StatusError } from "@/api/utils";
|
import { StatusError } from "@/api/utils";
|
||||||
|
import { setSafeTimeout } from "@/api/utils";
|
||||||
|
|
||||||
export function parseToken(token: string) {
|
export function parseToken(token: string) {
|
||||||
// falsy or malformed jwt will throw InvalidTokenError
|
// falsy or malformed jwt will throw InvalidTokenError
|
||||||
@@ -16,6 +17,18 @@ export function parseToken(token: string) {
|
|||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
authStore.jwt = token;
|
authStore.jwt = token;
|
||||||
authStore.setUser(data.user);
|
authStore.setUser(data.user);
|
||||||
|
|
||||||
|
if (authStore.logoutTimer) {
|
||||||
|
clearTimeout(authStore.logoutTimer);
|
||||||
|
}
|
||||||
|
|
||||||
|
const expiresAt = new Date(data.exp! * 1000);
|
||||||
|
const timeout = expiresAt.getTime() - Date.now();
|
||||||
|
authStore.setLogoutTimer(
|
||||||
|
setSafeTimeout(() => {
|
||||||
|
logout("inactivity");
|
||||||
|
}, timeout)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function validateLogin() {
|
export async function validateLogin() {
|
||||||
@@ -92,7 +105,7 @@ export async function signup(username: string, password: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function logout() {
|
export function logout(reason?: string) {
|
||||||
document.cookie = "auth=; Max-Age=0; Path=/; SameSite=Strict;";
|
document.cookie = "auth=; Max-Age=0; Path=/; SameSite=Strict;";
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
@@ -102,6 +115,15 @@ export function logout() {
|
|||||||
if (noAuth) {
|
if (noAuth) {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
} else {
|
} else {
|
||||||
router.push({ path: "/login" });
|
if (typeof reason === "string" && reason.trim() !== "") {
|
||||||
|
router.push({
|
||||||
|
path: "/login",
|
||||||
|
query: { "logout-reason": reason },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
router.push({
|
||||||
|
path: "/login",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import { theme } from "./constants";
|
import { theme } from "./constants";
|
||||||
|
import "ace-builds";
|
||||||
|
import { themesByName } from "ace-builds/src-noconflict/ext-themelist";
|
||||||
|
|
||||||
export const getTheme = (): UserTheme => {
|
export const getTheme = (): UserTheme => {
|
||||||
return (document.documentElement.className as UserTheme) || theme;
|
return (document.documentElement.className as UserTheme) || theme;
|
||||||
@@ -32,3 +34,17 @@ export const getMediaPreference = (): UserTheme => {
|
|||||||
return "light";
|
return "light";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getEditorTheme = (themeName: string) => {
|
||||||
|
if (!themeName.startsWith("ace/theme/")) {
|
||||||
|
themeName = `ace/theme/${themeName}`;
|
||||||
|
}
|
||||||
|
const themeKey = themeName.replace("ace/theme/", "");
|
||||||
|
if (themesByName[themeKey] !== undefined) {
|
||||||
|
return themeName;
|
||||||
|
} else if (getTheme() === "dark") {
|
||||||
|
return "ace/theme/twilight";
|
||||||
|
} else {
|
||||||
|
return "ace/theme/chrome";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
<form @submit="submit">
|
<form @submit="submit">
|
||||||
<img :src="logoURL" alt="File Browser" />
|
<img :src="logoURL" alt="File Browser" />
|
||||||
<h1>{{ name }}</h1>
|
<h1>{{ name }}</h1>
|
||||||
|
<p v-if="reason != null" class="logout-message">
|
||||||
|
{{ t(`login.logout_reasons.${reason}`) }}
|
||||||
|
</p>
|
||||||
<div v-if="error !== ''" class="wrong">{{ error }}</div>
|
<div v-if="error !== ''" class="wrong">{{ error }}</div>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
@@ -70,6 +73,8 @@ const toggleMode = () => (createMode.value = !createMode.value);
|
|||||||
|
|
||||||
const $showError = inject<IToastError>("$showError")!;
|
const $showError = inject<IToastError>("$showError")!;
|
||||||
|
|
||||||
|
const reason = route.query["logout-reason"] ?? null;
|
||||||
|
|
||||||
const submit = async (event: Event) => {
|
const submit = async (event: Event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|||||||