├── .github ├── ISSUE_TEMPLATE │ ├── bug.md │ └── feature_request.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── MANIFEST.in ├── README.md ├── filebrowser ├── __init__.py ├── app.py ├── funcs.py ├── main.py ├── static │ ├── css │ │ ├── file.css │ │ └── file1.css │ ├── fonts │ │ └── MaterialIcons-Regular.570eb838.woff2 │ └── js │ │ └── main.js └── templates │ ├── data.html │ └── index.html ├── requirements.dev.txt ├── requirements.txt └── setup.py /.github/ISSUE_TEMPLATE/bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug 3 | about: Report a bug or unexpected behavior. 4 | 5 | --- 6 | 7 | 8 | 9 | **Describe the bug** 10 | 11 | 12 | **How to reproduce** 13 | 14 | 15 | **Expected behavior** 16 | 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea or new feature for this project 4 | 5 | --- 6 | 7 | **How would this feature be useful?** 8 | 9 | 10 | **Describe the solution you'd like** 11 | 12 | 13 | **Describe alternatives you've considered** 14 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | filebrowser/static/js/jquery.min.js 2 | 3 | # Byte-compiled 4 | __pycache__* 5 | 6 | # Distribution / packaging 7 | .Python 8 | build/ 9 | develop-eggs/ 10 | dist/ 11 | downloads/ 12 | eggs/ 13 | .eggs/ 14 | lib/ 15 | lib64/ 16 | parts/ 17 | sdist/ 18 | var/ 19 | wheels/ 20 | share/python-wheels/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | MANIFEST -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # filebrowser 2 | 3 | ### _Changelog_ 4 | 5 | - `dev` 6 | - update flask to latest version and fix download 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 Jak Bin. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # filebrowser 2 | 3 | The single page web file browser that use ajax. 4 | 5 | ![flask](https://img.shields.io/badge/flask-≤2.0-green.svg) 6 | [![PyPI version](https://badge.fury.io/py/filebrowser.svg)](https://pypi.org/project/filebrowser/) 7 | [![Downloads](https://pepy.tech/badge/filebrowser/month)](https://pepy.tech/project/filebrowser) 8 | [![Downloads](https://static.pepy.tech/personalized-badge/filebrowser?period=total&units=international_system&left_color=green&right_color=blue&left_text=Total%20Downloads)](https://pepy.tech/project/filebrowser) 9 | 10 | ## Features 11 | 12 | * Create Folder and File 13 | * Delete Folder and File 14 | * Rename Folder and File 15 | * Download File and Folder (folder as zip) 16 | * File and Folder size 17 | * File Upload 18 | * Drag and Drop file upload 19 | * copy File and folder 20 | * move File and folder 21 | 22 | ## Installation 23 | 24 | ```sh 25 | pip3 install filebrowser 26 | ``` 27 | 28 | ## Usage 29 | 30 | ```sh 31 | filebrowser 32 | 33 | filebrowser --host {custom_address} --port {custom_port} --dir {folder_path} 34 | 35 | filebrowser --host {custom_address} -p {custom_port} -d {folder_path} 36 | ``` 37 | 38 | ## To do 39 | - [ ] Use pure js. 40 | - [ ] Comment code. 41 | - [ ] Use socket. 42 | 43 | 44 | ### Support my work :- 45 | 46 | BTC - bc1qx2p08qtsxxdzj0yfr2cm7yy3g5ydv3mt2753le\ 47 | ETH - 0x40e69DaEC18cD199535b055BDA6582daa5978145 -------------------------------------------------------------------------------- /filebrowser/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = "1.1.4" -------------------------------------------------------------------------------- /filebrowser/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template, request, flash, send_from_directory, json, Response 2 | from werkzeug.utils import secure_filename 3 | import os 4 | from datetime import datetime 5 | from shutil import rmtree 6 | import tempfile 7 | from zipfile import ZipFile 8 | import shutil 9 | 10 | from filebrowser.funcs import get_size, diff, folderCompare 11 | 12 | def server(host:str=None, port:int=None, home_path:str=None): 13 | app = Flask(__name__) 14 | app.secret_key = os.urandom(32) 15 | 16 | @app.route("/") 17 | def home(): 18 | return render_template('index.html') 19 | 20 | @app.route("/load-data", methods=['POST']) 21 | def loaddata(): 22 | data = request.get_json() 23 | name = data['name'] 24 | folder = data['folder'] 25 | curr_path = os.path.join(home_path, folder, name) 26 | folders = [] 27 | folders_date = [] 28 | files = [] 29 | files_size = [] 30 | files_date = [] 31 | if folderCompare(home_path, curr_path): 32 | dir_list = os.listdir(curr_path) 33 | for item in dir_list: 34 | if os.path.isdir(os.path.join(curr_path,item)): 35 | folders.append(item) 36 | folder_date = diff(os.path.join(curr_path,item)) 37 | folders_date.append(folder_date) 38 | for item in dir_list: 39 | if os.path.isfile(os.path.join(curr_path,item)): 40 | files.append(item) 41 | file_size = get_size(os.path.join(curr_path,item)) 42 | files_size.append(file_size) 43 | file_date = diff(os.path.join(curr_path,item)) 44 | files_date.append(file_date) 45 | 46 | folders_data = list(zip(folders, folders_date)) 47 | files_data = list(zip(files, files_size, files_date)) 48 | 49 | return render_template('data.html', folders_data=folders_data, files_data=files_data) 50 | else: 51 | return '0', 201 52 | 53 | @app.route('/info') 54 | def info(): 55 | foldername = os.path.basename(home_path) 56 | lastmd = diff(home_path) 57 | dir_list = os.listdir(home_path) 58 | file = 0 59 | folder = 0 60 | for item in dir_list: 61 | if os.path.isdir(item): 62 | folder+=1 63 | elif os.path.isfile(item): 64 | file+=1 65 | data = {'foldername': foldername, 'lastmd': lastmd, 'file': file, 'folder': folder} 66 | return custom_response(data, 200) 67 | 68 | def custom_response(res, status_code): 69 | return Response(mimetype="application/json",response=json.dumps(res),status=status_code) 70 | 71 | @app.route('/folderlist', methods=['POST']) 72 | def folderlist(): 73 | data = request.get_json() 74 | foldername = data['foldername'] 75 | folder = data['folder'] 76 | curr_path = os.path.join(home_path, folder, foldername) 77 | if folderCompare(home_path, curr_path) and str(curr_path) != (str(os.path.join(home_path,'..'))): 78 | dir_list = os.listdir(curr_path) 79 | folders = [] 80 | for item in dir_list: 81 | if os.path.isdir(os.path.join(curr_path,item)): 82 | folders.append({"path":item }) 83 | return {"item":folders} 84 | else: 85 | return {"item":"no more folder", "status":False} 86 | 87 | @app.route('/copyItem', methods=['POST']) 88 | def copyItem(): 89 | data = request.get_json() 90 | source = data['source'] 91 | itemName = data['itemName'] 92 | destination = data['destination'] 93 | fodestination = data['fodestination'] 94 | fullSource = os.path.join(home_path, source, itemName) 95 | fullDestination = os.path.join(home_path, source, fodestination, destination) 96 | try: 97 | shutil.copy2(fullSource, fullDestination) 98 | return '1' 99 | except NotADirectoryError: 100 | shutil.copytree(fullSource, fullDestination) 101 | return '1' 102 | else: 103 | return '0' 104 | 105 | @app.route('/moveItem', methods=['POST']) 106 | def moveItem(): 107 | data = request.get_json() 108 | source = data['source'] 109 | destination = data['destination'] 110 | itemName = data['itemName'] 111 | fodestination = data['fodestination'] 112 | fullSource = os.path.join(home_path, source, itemName) 113 | fullDestination = os.path.join(home_path, source, fodestination, destination) 114 | try: 115 | shutil.move(fullSource, fullDestination) 116 | return '1' 117 | except NotADirectoryError: 118 | shutil.copytree(fullSource, fullDestination) 119 | return '1' 120 | else: 121 | return '0' 122 | 123 | @app.route("/new-folder", methods = ['POST']) 124 | def newfolder(): 125 | data = request.get_json() 126 | name = data['name'] 127 | folder = data['folder'] 128 | try: 129 | os.mkdir(os.path.join(home_path, folder, name)) 130 | return "1" 131 | except IOError as e: 132 | return str(e) 133 | 134 | @app.route("/new-file", methods = ['POST']) 135 | def newfile(): 136 | data = request.get_json() 137 | name = data['name'] 138 | folder = data['folder'] 139 | file = os.path.join(home_path, folder, name) 140 | try: 141 | with open(file, 'w') as fp: 142 | pass 143 | return "1" 144 | except IOError as e: 145 | return str(e) 146 | 147 | @app.route("/upload", methods = ['POST']) 148 | def upload(): 149 | folder = request.form.get('folder') 150 | target = os.path.join(home_path, folder) 151 | f = request.files['file1'] 152 | if f.filename == "": 153 | return 'No file selected' 154 | elif f: 155 | f.save(os.path.join(target, secure_filename(f.filename))) 156 | return "1" 157 | 158 | @app.route("/delete", methods = ['POST']) 159 | def delete(): 160 | data = request.get_json() 161 | name = data['name'] 162 | folder = data['folder'] 163 | target = os.path.join(home_path, folder, name) 164 | if os.path.isdir(target): 165 | folders = os.listdir(target) 166 | if folders == []: 167 | try: 168 | os.rmdir(target) 169 | return "1" 170 | except IOError as e: 171 | return str(e) 172 | else: 173 | try: 174 | rmtree(target) 175 | return "1" 176 | except IOError as e: 177 | return str(e) 178 | else: 179 | os.path.isfile(target) 180 | try: 181 | os.remove(target) 182 | return "1" 183 | except IOError as e: 184 | return str(e) 185 | 186 | @app.route("/rename", methods = ['POST']) 187 | def rename(): 188 | data = request.get_json() 189 | print(data) 190 | name = data['name'] 191 | folder = data['folder'] 192 | dst = data['dst'] 193 | target = os.path.join(home_path, folder, name) 194 | fullDestination = os.path.join(home_path, folder, dst) 195 | try: 196 | os.rename(target, fullDestination) 197 | return "1" 198 | except IOError as e: 199 | return str(e) 200 | 201 | @app.route("/download/") 202 | def download(name): 203 | target = os.path.join(home_path, name) 204 | def get_all_dir(directory): 205 | file_paths = list() 206 | for root, directories, files in os.walk(directory): 207 | for filename in files: 208 | filepath = os.path.join(root, filename) 209 | file_paths.append(filepath) 210 | return file_paths 211 | 212 | if os.path.isdir(target): 213 | os.chdir(os.path.dirname(target)) 214 | foldername = os.path.basename(target) 215 | file_paths = get_all_dir(foldername) 216 | temp_dir = tempfile.gettempdir() 217 | zipname = os.path.join(temp_dir, foldername) 218 | 219 | try: 220 | with ZipFile(f"{foldername}.zip", "w") as zip: 221 | for file in file_paths: 222 | zip.write(file) 223 | return send_from_directory(directory=os.path.dirname(target), path=f"{foldername}.zip", as_attachment=True) 224 | 225 | finally: 226 | if os.path.exists(f"{foldername}.zip"): 227 | os.remove(f"{foldername}.zip") 228 | else: 229 | try: 230 | return send_from_directory(directory=os.path.dirname(target), path=os.path.basename(target), as_attachment=True) 231 | except IOError: 232 | return "can't download" 233 | 234 | app.run(host=host, port=port, debug=True) 235 | -------------------------------------------------------------------------------- /filebrowser/funcs.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import datetime 4 | import platform 5 | 6 | def get_size(path): 7 | size = os.path.getsize(path) 8 | if size < 1024: 9 | return f"{size} B" 10 | elif size < 1024*1024: 11 | return f"{round(size/1024, 2)} KB" 12 | elif size < 1024*1024*1024: 13 | return f"{round(size/(1024*1024), 2)} MB" 14 | elif size < 1024*1024*1024*1024: 15 | return f"{round(size/(1024*1024*1024), 2)} GB" 16 | 17 | def diff(file): 18 | today = datetime.datetime.today() 19 | 20 | file_mtime = time.ctime(os.path.getmtime(file)) 21 | t_ob = time.strptime(file_mtime) 22 | t = time.strftime("%Y-%m-%d %H-%M-%S", t_ob) 23 | file_d = datetime.datetime.strptime(t, "%Y-%m-%d %H-%M-%S") 24 | 25 | minutes = divmod((today-file_d).total_seconds(), 60) 26 | 27 | if (today - file_d).days > 30: 28 | return f"{round(((today - file_d).days)/30)} months" 29 | elif (today - file_d).days != 0: 30 | return f"{(today - file_d).days} days" 31 | elif minutes[0] > 59: 32 | return f"{round(minutes[0]/60)} huors" 33 | elif minutes[0] != 0: 34 | return f"{round(minutes[0])} minutes" 35 | else: 36 | return f"{round(minutes[1])} seconds" 37 | 38 | pl = platform.system() 39 | 40 | def folderCompare(base_path, path): 41 | if pl == 'Windows': 42 | base_path = str(base_path).split('\\') 43 | path = str(path).split('\\') 44 | else: 45 | base_path = str(base_path).split('/') 46 | path = str(path).split('/') 47 | result = True 48 | for i in base_path: 49 | if i in path: 50 | result = True 51 | else: 52 | result = False 53 | break 54 | return result 55 | -------------------------------------------------------------------------------- /filebrowser/main.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | from pathlib import Path 3 | from filebrowser.app import server 4 | 5 | package_name = "filebrowser" 6 | 7 | example_uses = '''example: 8 | filebrowser 9 | filebrowser --host {custom_address} --port {custom_port} --dir {folder_path} 10 | filebrowser --host {custom_address} -p {custom_port} -d {folder_path}''' 11 | 12 | def run_server(address, port, path): 13 | server(address, port, path) 14 | 15 | def main(argv = None): 16 | parser = argparse.ArgumentParser(prog=package_name, description="Simple web file browser.", epilog=example_uses, formatter_class=argparse.RawDescriptionHelpFormatter) 17 | 18 | parser.add_argument("--host", dest="host", metavar="host", type=str, default="127.0.0.1", help="address to listen (default: 127.0.0.1)") 19 | 20 | parser.add_argument('-p',"--port", dest="port", metavar="port", type=int, default=8080, help="port to listen (default: 8080)") 21 | 22 | parser.add_argument('-d',"--dir", dest="dir", metavar="path", type=str, default=Path.cwd(), help="serving directory (default: current directory)") 23 | 24 | parser.add_argument('-v',"--version", action="store_true", dest="version", help="check version of filebrowser") 25 | 26 | args = parser.parse_args(argv) 27 | 28 | if bool(args.host) or bool(args.port) or bool(args.dir): 29 | return run_server(args.host, args.port, args.dir) 30 | elif args.version: 31 | return __version__ 32 | else: 33 | return run_server("127.0.0.1", 8080, Path.cwd()) 34 | 35 | if __name__ == "__main__": 36 | raise SystemExit(main()) -------------------------------------------------------------------------------- /filebrowser/static/css/file.css: -------------------------------------------------------------------------------- 1 | .image-ex-container { 2 | margin: auto; 3 | overflow: hidden; 4 | position: relative; 5 | } 6 | .image-ex-img { 7 | position: absolute; 8 | } 9 | .image-ex-img-center { 10 | left: 50%; 11 | top: 50%; 12 | -webkit-transform: translate(-50%, -50%); 13 | transform: translate(-50%, -50%); 14 | position: absolute; 15 | -webkit-transition: none; 16 | transition: none; 17 | } 18 | .image-ex-img-ready { 19 | left: 0; 20 | top: 0; 21 | -webkit-transition: -webkit-transform 0.1s ease; 22 | transition: -webkit-transform 0.1s ease; 23 | transition: transform 0.1s ease; 24 | transition: transform 0.1s ease, -webkit-transform 0.1s ease; 25 | } 26 | :root { 27 | --blue: #2196f3; 28 | --dark-blue: #1e88e5; 29 | --red: #f44336; 30 | --dark-red: #d32f2f; 31 | --moon-grey: #f2f2f2; 32 | } 33 | .button { 34 | outline: 0; 35 | border: 0; 36 | padding: 0.5em 1em; 37 | border-radius: 0.1em; 38 | cursor: pointer; 39 | background: var(--blue); 40 | color: #fff; 41 | border: 1px solid rgba(0, 0, 0, 0.05); 42 | -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.05); 43 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.05); 44 | -webkit-transition: all 0.1s ease; 45 | transition: all 0.1s ease; 46 | } 47 | /*.button:hover { 48 | background-color: var(--dark-blue); 49 | }*/ 50 | .button--block { 51 | margin: 0 0 0.5em; 52 | display: block; 53 | width: 100%; 54 | } 55 | .button--red { 56 | background: var(--red); 57 | } 58 | .button--blue { 59 | background: var(--blue); 60 | } 61 | .button--flat { 62 | color: var(--dark-blue); 63 | background: transparent; 64 | -webkit-box-shadow: 0 0 0; 65 | box-shadow: 0 0 0; 66 | border: 0; 67 | text-transform: uppercase; 68 | } 69 | .button--flat:hover { 70 | background: var(--moon-grey); 71 | } 72 | .button--flat.button--red { 73 | color: var(--dark-red); 74 | } 75 | .button--flat.button--grey { 76 | color: #6f6f6f; 77 | } 78 | .button[disabled] { 79 | opacity: 0.5; 80 | cursor: not-allowed; 81 | } 82 | .input { 83 | border-radius: 0.1em; 84 | padding: 0.5em 1em; 85 | background: #fff; 86 | border: 1px solid rgba(0, 0, 0, 0.1); 87 | -webkit-transition: all 0.2s ease; 88 | transition: all 0.2s ease; 89 | color: #333; 90 | margin: 0; 91 | } 92 | .input:focus, 93 | .input:hover { 94 | border-color: rgba(0, 0, 0, 0.2); 95 | } 96 | .input--block { 97 | margin-bottom: 0.5em; 98 | display: block; 99 | width: 100%; 100 | } 101 | .input--textarea { 102 | line-height: 1.15; 103 | font-family: monospace; 104 | min-height: 10em; 105 | resize: vertical; 106 | } 107 | .input--red { 108 | background: #fcd0cd; 109 | } 110 | .input--green { 111 | background: #c9f2da; 112 | } 113 | .material-icons { 114 | font-size: 1.5rem; 115 | } 116 | body { 117 | font-family: Roboto, sans-serif; 118 | padding-top: 4em; 119 | background-color: #fafafa; 120 | color: #333; 121 | } 122 | * { 123 | -webkit-box-sizing: border-box; 124 | box-sizing: border-box; 125 | } 126 | *, 127 | :active, 128 | :focus, 129 | :hover { 130 | outline: 0; 131 | } 132 | a { 133 | text-decoration: none; 134 | } 135 | img { 136 | max-width: 100%; 137 | } 138 | audio, 139 | video { 140 | width: 100%; 141 | } 142 | .mobile-only { 143 | display: none !important; 144 | } 145 | .container { 146 | width: 95%; 147 | max-width: 960px; 148 | margin: 1em auto 0; 149 | } 150 | i.spin { 151 | -webkit-animation: spin 1s linear infinite; 152 | animation: spin 1s linear infinite; 153 | } 154 | #app { 155 | -webkit-transition: padding 0.2s ease; 156 | transition: padding 0.2s ease; 157 | } 158 | #app.multiple { 159 | padding-bottom: 4em; 160 | } 161 | nav { 162 | width: 16em; 163 | position: fixed; 164 | top: 4em; 165 | left: 0; 166 | } 167 | nav .action { 168 | width: 100%; 169 | display: block; 170 | border-radius: 0; 171 | font-size: 1.1em; 172 | padding: 0.5em; 173 | white-space: nowrap; 174 | overflow: hidden; 175 | text-overflow: ellipsis; 176 | } 177 | nav > div { 178 | border-top: 1px solid rgba(0, 0, 0, 0.05); 179 | } 180 | nav .action > * { 181 | vertical-align: middle; 182 | } 183 | main { 184 | min-height: 1em; 185 | margin: 0 1em 1em auto; 186 | width: calc(100% - 19em); 187 | } 188 | .breadcrumbs { 189 | height: 3em; 190 | border-bottom: 1px solid rgba(0, 0, 0, 0.05); 191 | } 192 | .breadcrumbs, 193 | .breadcrumbs span { 194 | display: -webkit-box; 195 | display: -ms-flexbox; 196 | display: flex; 197 | -webkit-box-align: center; 198 | -ms-flex-align: center; 199 | align-items: center; 200 | color: #6f6f6f; 201 | } 202 | .breadcrumbs a { 203 | color: inherit; 204 | -webkit-transition: 0.1s ease-in; 205 | transition: 0.1s ease-in; 206 | border-radius: 0.125em; 207 | } 208 | .breadcrumbs a:hover { 209 | background-color: rgba(0, 0, 0, 0.05); 210 | } 211 | .breadcrumbs span a { 212 | padding: 0.2em; 213 | } 214 | #progress { 215 | position: fixed; 216 | top: 0; 217 | left: 0; 218 | width: 100%; 219 | height: 3px; 220 | z-index: 9999999999; 221 | } 222 | #progress div { 223 | height: 100%; 224 | background-color: #40c4ff; 225 | width: 0; 226 | -webkit-transition: width 0.2s ease; 227 | transition: width 0.2s ease; 228 | } 229 | .break-word { 230 | word-break: break-all; 231 | } 232 | header { 233 | z-index: 1000; 234 | background-color: #fff; 235 | border-bottom: 1px solid rgba(0, 0, 0, 0.075); 236 | -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); 237 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); 238 | position: fixed; 239 | top: 0; 240 | left: 0; 241 | height: 4em; 242 | width: 100%; 243 | padding: 0; 244 | display: -webkit-box; 245 | display: -ms-flexbox; 246 | display: flex; 247 | padding: 0.5em 0.5em 0.5em 1em; 248 | -webkit-box-align: center; 249 | -ms-flex-align: center; 250 | align-items: center; 251 | } 252 | header > * { 253 | -webkit-box-flex: 0; 254 | -ms-flex: 0 0 auto; 255 | flex: 0 0 auto; 256 | } 257 | header title { 258 | display: block; 259 | -webkit-box-flex: 1; 260 | -ms-flex: 1 1 auto; 261 | flex: 1 1 auto; 262 | padding: 0 1em; 263 | overflow: hidden; 264 | text-overflow: ellipsis; 265 | font-size: 1.2em; 266 | } 267 | header .overlay { 268 | width: 0; 269 | height: 0; 270 | } 271 | header a, 272 | header a:hover { 273 | color: inherit; 274 | } 275 | header > div:first-child > .action, 276 | header img { 277 | margin-right: 1em; 278 | } 279 | header img { 280 | height: 2.5em; 281 | } 282 | header .action span { 283 | display: none; 284 | } 285 | header > div div { 286 | vertical-align: middle; 287 | position: relative; 288 | } 289 | #more, 290 | header .menu-button, 291 | header .search-button { 292 | display: none; 293 | } 294 | #listing h2 { 295 | margin: 0 0 0 0.5em; 296 | font-size: 0.9em; 297 | color: rgba(0, 0, 0, 0.38); 298 | font-weight: 500; 299 | } 300 | #listing .item div:last-of-type * { 301 | text-overflow: ellipsis; 302 | overflow: hidden; 303 | } 304 | 305 | /*my custom css*/ 306 | #listing .myheader { 307 | -ms-flex-wrap: wrap; 308 | flex-wrap: wrap; 309 | -webkit-box-pack: start; 310 | -ms-flex-pack: start; 311 | justify-content: flex-start; 312 | } 313 | 314 | #listing .mycustom > div { 315 | -ms-flex-wrap: wrap; 316 | flex-wrap: wrap; 317 | -webkit-box-pack: start; 318 | -ms-flex-pack: start; 319 | justify-content: flex-start; 320 | } 321 | 322 | #listing .item, 323 | #listing .myheader { 324 | display: -webkit-box; 325 | display: -ms-flexbox; 326 | display: flex; 327 | } 328 | 329 | #listing .mycustom > div { 330 | display: -webkit-box; 331 | display: -ms-flexbox; 332 | display: flex; 333 | } 334 | /*my custom css end */ 335 | #listing .item { 336 | background-color: #fff; 337 | position: relative; 338 | -ms-flex-wrap: nowrap; 339 | flex-wrap: nowrap; 340 | color: #6f6f6f; 341 | -webkit-transition: background 0.1s ease, opacity 0.1s ease; 342 | transition: background 0.1s ease, opacity 0.1s ease; 343 | -webkit-box-align: center; 344 | -ms-flex-align: center; 345 | align-items: center; 346 | cursor: pointer; 347 | -webkit-user-select: none; 348 | -moz-user-select: none; 349 | -ms-user-select: none; 350 | user-select: none; 351 | } 352 | #listing .item div:last-of-type { 353 | text-overflow: ellipsis; 354 | white-space: nowrap; 355 | overflow: hidden; 356 | } 357 | #listing .item p { 358 | margin: 0; 359 | } 360 | #listing .item .modified, 361 | #listing .item .size { 362 | font-size: 0.9em; 363 | } 364 | #listing .item .name { 365 | font-weight: 700; 366 | } 367 | #listing .item i { 368 | font-size: 4em; 369 | } 370 | #listing .item i, 371 | #listing .item img { 372 | margin-right: 0.1em; 373 | vertical-align: bottom; 374 | } 375 | #listing .item img { 376 | width: 4em; 377 | height: 4em; 378 | -o-object-fit: cover; 379 | object-fit: cover; 380 | } 381 | .message { 382 | text-align: center; 383 | font-size: 2em; 384 | margin: 1em auto; 385 | display: block !important; 386 | width: 95%; 387 | color: rgba(0, 0, 0, 0.3); 388 | font-weight: 500; 389 | } 390 | .message i { 391 | font-size: 2.5em; 392 | margin-bottom: 0.2em; 393 | display: block; 394 | } 395 | #listing.mosaic { 396 | padding-top: 1em; 397 | margin: 0 -0.5em; 398 | } 399 | #listing.mosaic .item { 400 | width: calc(33% - 1em); 401 | margin: 0.5em; 402 | padding: 0.5em; 403 | border-radius: 0.2em; 404 | -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.12); 405 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.12); 406 | } 407 | #listing.mosaic .item:hover { 408 | -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24) !important; 409 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24) !important; 410 | } 411 | #listing.mosaic .header { 412 | display: none; 413 | } 414 | #listing.mosaic .item div:first-of-type { 415 | width: 5em; 416 | } 417 | #listing.mosaic .item div:last-of-type { 418 | width: calc(100% - 5vw); 419 | } 420 | #listing.list { 421 | -webkit-box-orient: vertical; 422 | -webkit-box-direction: normal; 423 | -ms-flex-direction: column; 424 | flex-direction: column; 425 | width: 100%; 426 | max-width: 100%; 427 | margin: 0; 428 | } 429 | #listing.list .item { 430 | width: 100%; 431 | margin: 0; 432 | border: 1px solid rgba(0, 0, 0, 0.1); 433 | padding: 1em; 434 | border-top: 0; 435 | } 436 | #listing.list h2 { 437 | display: none; 438 | } 439 | #listing .item[aria-selected="true"] { 440 | background: var(--blue) !important; 441 | color: #fff !important; 442 | } 443 | #listing.list .item div:first-of-type { 444 | width: 3em; 445 | } 446 | #listing.list .item div:first-of-type i { 447 | font-size: 2em; 448 | } 449 | #listing.list .item div:first-of-type img { 450 | width: 2em; 451 | height: 2em; 452 | } 453 | #listing.list .item div:last-of-type { 454 | width: calc(100% - 3em); 455 | display: -webkit-box; 456 | display: -ms-flexbox; 457 | display: flex; 458 | -webkit-box-align: center; 459 | -ms-flex-align: center; 460 | align-items: center; 461 | } 462 | #listing.list .item .name { 463 | width: 50%; 464 | } 465 | #listing.list .item .size { 466 | width: 25%; 467 | } 468 | #listing .item.header { 469 | display: none !important; 470 | background-color: #ccc; 471 | } 472 | #listing.list .header i { 473 | font-size: 1.5em; 474 | vertical-align: middle; 475 | margin-left: 0.2em; 476 | } 477 | #listing.list .item.header { 478 | display: -webkit-box !important; 479 | display: -ms-flexbox !important; 480 | display: flex !important; 481 | background: #fafafa; 482 | z-index: 999; 483 | padding: 0.85em; 484 | border: 0; 485 | border-bottom: 1px solid rgba(0, 0, 0, 0.1); 486 | } 487 | #listing.list .header a { 488 | color: inherit; 489 | } 490 | #listing.list .item.header > div:first-child { 491 | width: 0; 492 | } 493 | #listing.list .name { 494 | font-weight: 400; 495 | } 496 | #listing.list .item.header .name { 497 | margin-right: 3em; 498 | } 499 | #listing.list .header span { 500 | vertical-align: middle; 501 | } 502 | #listing.list .header i { 503 | opacity: 0; 504 | -webkit-transition: all 0.1s ease; 505 | transition: all 0.1s ease; 506 | } 507 | #listing.list .header .active i, 508 | #listing.list .header p:hover i { 509 | opacity: 1; 510 | } 511 | #listing.list .item.header .active { 512 | font-weight: 700; 513 | } 514 | #listing #multiple-selection { 515 | position: fixed; 516 | bottom: -4em; 517 | left: 0; 518 | z-index: 99999; 519 | width: 100%; 520 | background-color: var(--blue); 521 | height: 4em; 522 | padding: 0.5em 0.5em 0.5em 1em; 523 | -webkit-box-pack: justify; 524 | -ms-flex-pack: justify; 525 | justify-content: space-between; 526 | -webkit-transition: bottom 0.2s ease; 527 | transition: bottom 0.2s ease; 528 | } 529 | #listing #multiple-selection.active { 530 | bottom: 0; 531 | } 532 | #listing #multiple-selection i, 533 | #listing #multiple-selection p { 534 | color: #fff; 535 | } 536 | li code, 537 | p code { 538 | background: rgba(0, 0, 0, 0.05); 539 | padding: 0.1em; 540 | border-radius: 0.2em; 541 | } 542 | .small { 543 | font-size: 0.8em; 544 | line-height: 1.5; 545 | } 546 | table { 547 | border-collapse: collapse; 548 | width: 100%; 549 | } 550 | table tr { 551 | border-bottom: 1px solid #ccc; 552 | } 553 | table tr:last-child { 554 | border: 0; 555 | } 556 | table th { 557 | font-weight: 500; 558 | color: #757575; 559 | text-align: left; 560 | } 561 | table td, 562 | table th { 563 | padding: 0.5em 0; 564 | } 565 | table td.small { 566 | width: 1em; 567 | } 568 | table tr > :first-child { 569 | padding-left: 1em; 570 | } 571 | table tr > :last-child { 572 | padding-right: 1em; 573 | } 574 | .card { 575 | position: relative; 576 | margin: 0 0 1rem 0; 577 | background-color: #fff; 578 | border-radius: 2px; 579 | -webkit-box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2); 580 | box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -2px rgba(0, 0, 0, 0.2); 581 | overflow: auto; 582 | } 583 | .card.floating { 584 | position: fixed; 585 | top: 50%; 586 | left: 50%; 587 | -webkit-transform: translate(-50%, -50%); 588 | transform: translate(-50%, -50%); 589 | max-width: 25em; 590 | width: 90%; 591 | max-height: 95%; 592 | z-index: 99999; 593 | -webkit-animation: show 0.1s forwards; 594 | animation: show 0.1s forwards; 595 | } 596 | .card > * > :first-child { 597 | margin-top: 0; 598 | } 599 | .card > * > :last-child { 600 | margin-bottom: 0; 601 | } 602 | .card .card-title { 603 | padding: 1.5em 1em 1em; 604 | display: -webkit-box; 605 | display: -ms-flexbox; 606 | display: flex; 607 | } 608 | .card .card-title > :first-child { 609 | margin-right: auto; 610 | } 611 | .card > div { 612 | padding: 1em 1em; 613 | } 614 | .card > div:first-child { 615 | padding-top: 1.5em; 616 | } 617 | .card > div:last-child { 618 | padding-bottom: 1.5em; 619 | } 620 | .card .card-title * { 621 | margin: 0; 622 | } 623 | .card .card-action { 624 | text-align: right; 625 | } 626 | .card .card-content.full { 627 | padding-bottom: 0; 628 | overflow: auto; 629 | } 630 | .card h2, 631 | .card h3 { 632 | font-weight: 500; 633 | } 634 | .card h3 { 635 | color: rgba(0, 0, 0, 0.53); 636 | font-size: 1em; 637 | margin: 2em 0 1em; 638 | } 639 | .card-content table { 640 | margin: 0 -1em; 641 | width: calc(100% + 2em); 642 | } 643 | .card code { 644 | word-wrap: break-word; 645 | } 646 | .card#download { 647 | max-width: 15em; 648 | } 649 | .card#share ul { 650 | list-style: none; 651 | padding: 0; 652 | margin: 0; 653 | } 654 | .card#share ul li { 655 | display: -webkit-box; 656 | display: -ms-flexbox; 657 | display: flex; 658 | -webkit-box-pack: justify; 659 | -ms-flex-pack: justify; 660 | justify-content: space-between; 661 | -webkit-box-align: center; 662 | -ms-flex-align: center; 663 | align-items: center; 664 | } 665 | .card#share ul li a { 666 | color: var(--blue); 667 | cursor: pointer; 668 | margin-right: auto; 669 | } 670 | .card#share ul li .action i { 671 | font-size: 1em; 672 | } 673 | .card#share ul li input, 674 | .card#share ul li select { 675 | padding: 0.2em; 676 | margin-right: 0.5em; 677 | border: 1px solid #dadada; 678 | } 679 | .card#share .action.copy-clipboard:after { 680 | content: "Copied!"; 681 | position: absolute; 682 | left: -25%; 683 | width: 150%; 684 | font-size: 0.6em; 685 | text-align: center; 686 | background: #44a6f5; 687 | color: #fff; 688 | padding: 0.5em 0.2em; 689 | border-radius: 0.4em; 690 | top: -2em; 691 | -webkit-transition: opacity 0.1s ease; 692 | transition: opacity 0.1s ease; 693 | opacity: 0; 694 | } 695 | .card#share .action.copy-clipboard.active:after { 696 | opacity: 1; 697 | } 698 | .card#share .input-group { 699 | display: -webkit-box; 700 | display: -ms-flexbox; 701 | display: flex; 702 | } 703 | .card#share .input-group * { 704 | border: none; 705 | } 706 | .card#share .input-group input { 707 | -webkit-box-flex: 1; 708 | -ms-flex: 1; 709 | flex: 1; 710 | } 711 | .overlay { 712 | background-color: rgba(0, 0, 0, 0.5); 713 | position: fixed; 714 | top: 0; 715 | left: 0; 716 | height: 100%; 717 | width: 100%; 718 | z-index: 9999; 719 | -webkit-animation: show 0.1s forwards; 720 | animation: show 0.1s forwards; 721 | } 722 | .file-list { 723 | max-height: 50vh; 724 | overflow: auto; 725 | list-style: none; 726 | margin: 0; 727 | padding: 0; 728 | width: 100%; 729 | } 730 | .file-list li { 731 | width: 100%; 732 | -webkit-user-select: none; 733 | -moz-user-select: none; 734 | -ms-user-select: none; 735 | user-select: none; 736 | border-radius: 0.2em; 737 | padding: 0.3em; 738 | } 739 | .file-list li[aria-selected="true"] { 740 | background: var(--blue) !important; 741 | color: #fff !important; 742 | -webkit-transition: all 0.1s ease; 743 | transition: all 0.1s ease; 744 | } 745 | /*.file-list li:hover { 746 | background-color: #e9eaeb; 747 | cursor: pointer; 748 | }*/ 749 | .file-list li:before { 750 | content: "folder"; 751 | color: #6f6f6f; 752 | vertical-align: middle; 753 | line-height: 1.4; 754 | font-family: Material Icons; 755 | font-size: 1.75em; 756 | margin-right: 0.25em; 757 | } 758 | .file-list li[aria-selected="true"]:before { 759 | color: #fff; 760 | } 761 | @-webkit-keyframes show { 762 | 0% { 763 | display: none; 764 | opacity: 0; 765 | } 766 | 1% { 767 | display: block; 768 | opacity: 0; 769 | } 770 | to { 771 | display: block; 772 | opacity: 1; 773 | } 774 | } 775 | @keyframes show { 776 | 0% { 777 | display: none; 778 | opacity: 0; 779 | } 780 | 1% { 781 | display: block; 782 | opacity: 0; 783 | } 784 | to { 785 | display: block; 786 | opacity: 1; 787 | } 788 | } 789 | .card .card-action.full { 790 | padding-top: 0; 791 | display: -webkit-box; 792 | display: -ms-flexbox; 793 | display: flex; 794 | -ms-flex-wrap: wrap; 795 | flex-wrap: wrap; 796 | } 797 | .card .card-action.full .action { 798 | -webkit-box-flex: 1; 799 | -ms-flex: 1; 800 | flex: 1; 801 | padding: 2em; 802 | border-radius: 0.2em; 803 | border: 1px solid rgba(0, 0, 0, 0.1); 804 | text-align: center; 805 | margin: 0 0.25em 0.5em; 806 | } 807 | .card .card-action.full .action i { 808 | display: block; 809 | padding: 0; 810 | margin-bottom: 0.25em; 811 | font-size: 4em; 812 | } 813 | .card .card-action.full .action .title { 814 | font-size: 1.5em; 815 | font-weight: 500; 816 | } 817 | @media (max-width: 1024px) { 818 | nav { 819 | width: 10em; 820 | } 821 | } 822 | @media (max-width: 1024px) { 823 | main { 824 | width: calc(100% - 13em); 825 | } 826 | } 827 | @media (max-width: 736px) { 828 | body { 829 | padding-bottom: 5em; 830 | } 831 | #listing.list .item .size { 832 | display: none; 833 | } 834 | #listing.list .item .name { 835 | width: 60%; 836 | } 837 | #more { 838 | display: inherit; 839 | } 840 | header .overlay { 841 | width: 100%; 842 | height: 100%; 843 | background-color: rgba(0, 0, 0, 0.1); 844 | } 845 | #dropdown { 846 | position: fixed; 847 | top: 1em; 848 | right: 1em; 849 | background-color: #fff; 850 | -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); 851 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); 852 | -webkit-transform: scale(0); 853 | transform: scale(0); 854 | -webkit-transition: transform 0.1s ease-in-out; 855 | transition: transform 0.1s ease-in-out; 856 | -webkit-transform-origin: top right; 857 | transform-origin: top right; 858 | z-index: 99999; 859 | } 860 | #dropdown, 861 | #dropdown > div { 862 | display: block; 863 | } 864 | #dropdown.active { 865 | -webkit-transform: scale(1); 866 | transform: scale(1); 867 | } 868 | #dropdown .action { 869 | display: -webkit-box; 870 | display: -ms-flexbox; 871 | display: flex; 872 | -webkit-box-align: center; 873 | -ms-flex-align: center; 874 | align-items: center; 875 | border-radius: 0; 876 | width: 100%; 877 | } 878 | #dropdown .action span:not(.counter) { 879 | display: inline-block; 880 | padding: 0.4em; 881 | } 882 | #dropdown .counter { 883 | left: 2.25em; 884 | } 885 | #file-selection { 886 | position: fixed; 887 | bottom: 1em; 888 | left: 50%; 889 | -webkit-transform: translateX(-50%); 890 | transform: translateX(-50%); 891 | display: -webkit-box; 892 | display: -ms-flexbox; 893 | display: flex; 894 | -webkit-box-align: center; 895 | -ms-flex-align: center; 896 | align-items: center; 897 | background: #fff; 898 | -webkit-box-shadow: rgba(0, 0, 0, 0.06) 0 1px 3px, rgba(0, 0, 0, 0.12) 0 1px 2px; 899 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.12); 900 | width: 95%; 901 | max-width: 20em; 902 | z-index: 1; 903 | } 904 | #file-selection .action { 905 | border-radius: 50%; 906 | width: auto; 907 | } 908 | #file-selection > span { 909 | display: inline-block; 910 | margin-left: 1em; 911 | color: #6f6f6f; 912 | margin-right: auto; 913 | } 914 | #file-selection .action span { 915 | display: none; 916 | } 917 | nav { 918 | top: 0; 919 | z-index: 99999; 920 | background: #fff; 921 | height: 100%; 922 | width: 16em; 923 | -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); 924 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); 925 | -webkit-transition: left 0.1s ease; 926 | transition: left 0.1s ease; 927 | left: -17em; 928 | } 929 | nav.active { 930 | left: 0; 931 | } 932 | header .menu-button, 933 | header .search-button { 934 | display: inherit; 935 | } 936 | header img { 937 | display: none; 938 | } 939 | #listing { 940 | margin-bottom: 5em; 941 | } 942 | main { 943 | margin: 0 1em; 944 | width: calc(100% - 2em); 945 | } 946 | #search { 947 | display: none; 948 | } 949 | #search.active { 950 | display: block; 951 | } 952 | } 953 | @media (max-width: 450px) { 954 | #listing.list .item .modified { 955 | display: none; 956 | } 957 | #listing.list .item .name { 958 | width: 100%; 959 | } 960 | } 961 | .link { 962 | color: var(--blue); 963 | } 964 | main .spinner { 965 | display: block; 966 | text-align: center; 967 | line-height: 0; 968 | padding: 1em 0; 969 | } 970 | main .spinner > div { 971 | width: 0.8em; 972 | height: 0.8em; 973 | margin: 0 0.1em; 974 | font-size: 1em; 975 | background-color: rgba(0, 0, 0, 0.3); 976 | border-radius: 100%; 977 | display: inline-block; 978 | -webkit-animation: sk-bouncedelay 1.4s ease-in-out infinite both; 979 | animation: sk-bouncedelay 1.4s ease-in-out infinite both; 980 | } 981 | main .spinner .bounce1 { 982 | -webkit-animation-delay: -0.32s; 983 | animation-delay: -0.32s; 984 | } 985 | main .spinner .bounce2 { 986 | -webkit-animation-delay: -0.16s; 987 | animation-delay: -0.16s; 988 | } 989 | .delayed { 990 | -webkit-animation: delayed 0.1s linear; 991 | animation: delayed 0.1s linear; 992 | } 993 | @-webkit-keyframes delayed { 994 | 0% { 995 | opacity: 0; 996 | } 997 | 99% { 998 | opacity: 0; 999 | } 1000 | to { 1001 | opacity: 1; 1002 | } 1003 | } 1004 | @keyframes delayed { 1005 | 0% { 1006 | opacity: 0; 1007 | } 1008 | 99% { 1009 | opacity: 0; 1010 | } 1011 | to { 1012 | opacity: 1; 1013 | } 1014 | } 1015 | .action { 1016 | display: inline-block; 1017 | cursor: pointer; 1018 | -webkit-transition: all 0.2s ease; 1019 | transition: all 0.2s ease; 1020 | border: 0; 1021 | margin: 0; 1022 | color: #546e7a; 1023 | border-radius: 50%; 1024 | background: transparent; 1025 | padding: 0; 1026 | -webkit-box-shadow: none; 1027 | box-shadow: none; 1028 | vertical-align: middle; 1029 | text-align: left; 1030 | position: relative; 1031 | } 1032 | .action.disabled { 1033 | opacity: 0.2; 1034 | cursor: not-allowed; 1035 | } 1036 | .action i { 1037 | padding: 0.4em; 1038 | -webkit-transition: all 0.1s ease-in-out; 1039 | transition: all 0.1s ease-in-out; 1040 | border-radius: 50%; 1041 | } 1042 | .action:hover { 1043 | background-color: rgba(0, 0, 0, 0.1); 1044 | } 1045 | .action ul { 1046 | position: absolute; 1047 | top: 0; 1048 | color: #7d7d7d; 1049 | list-style: none; 1050 | margin: 0; 1051 | padding: 0; 1052 | -webkit-box-orient: vertical; 1053 | -webkit-box-direction: normal; 1054 | -ms-flex-direction: column; 1055 | flex-direction: column; 1056 | display: -webkit-box; 1057 | display: -ms-flexbox; 1058 | display: flex; 1059 | } 1060 | .action ul li { 1061 | line-height: 1; 1062 | padding: 0.7em; 1063 | -webkit-transition: background-color 0.1s ease; 1064 | transition: background-color 0.1s ease; 1065 | } 1066 | .action ul li:hover { 1067 | background-color: rgba(0, 0, 0, 0.04); 1068 | } 1069 | #click-overlay { 1070 | display: none; 1071 | position: fixed; 1072 | cursor: pointer; 1073 | top: 0; 1074 | left: 0; 1075 | height: 100%; 1076 | width: 100%; 1077 | } 1078 | #click-overlay.active { 1079 | display: block; 1080 | } 1081 | .action .counter { 1082 | display: block; 1083 | position: absolute; 1084 | bottom: 0; 1085 | right: 0; 1086 | background: var(--blue); 1087 | color: #fff; 1088 | border-radius: 50%; 1089 | font-size: 0.75em; 1090 | width: 1.8em; 1091 | height: 1.8em; 1092 | text-align: center; 1093 | line-height: 1.55em; 1094 | font-weight: 700; 1095 | border: 2px solid #fff; 1096 | } 1097 | @-webkit-keyframes spin { 1098 | to { 1099 | -webkit-transform: rotate(-1turn); 1100 | transform: rotate(-1turn); 1101 | } 1102 | } 1103 | @keyframes spin { 1104 | to { 1105 | -webkit-transform: rotate(-1turn); 1106 | transform: rotate(-1turn); 1107 | } 1108 | } 1109 | -------------------------------------------------------------------------------- /filebrowser/static/css/file1.css: -------------------------------------------------------------------------------- 1 | html { 2 | line-height: 1.15; 3 | -webkit-text-size-adjust: 100%; 4 | } 5 | body { 6 | margin: 0; 7 | } 8 | main { 9 | display: block; 10 | } 11 | h1 { 12 | font-size: 2em; 13 | margin: 0.67em 0; 14 | } 15 | hr { 16 | -webkit-box-sizing: content-box; 17 | box-sizing: content-box; 18 | height: 0; 19 | overflow: visible; 20 | } 21 | pre { 22 | font-family: monospace, monospace; 23 | font-size: 1em; 24 | } 25 | a { 26 | background-color: transparent; 27 | } 28 | abbr[title] { 29 | border-bottom: none; 30 | text-decoration: underline; 31 | -webkit-text-decoration: underline dotted; 32 | text-decoration: underline dotted; 33 | } 34 | b, 35 | strong { 36 | font-weight: bolder; 37 | } 38 | code, 39 | kbd, 40 | samp { 41 | font-family: monospace, monospace; 42 | font-size: 1em; 43 | } 44 | small { 45 | font-size: 80%; 46 | } 47 | sub, 48 | sup { 49 | font-size: 75%; 50 | line-height: 0; 51 | position: relative; 52 | vertical-align: baseline; 53 | } 54 | sub { 55 | bottom: -0.25em; 56 | } 57 | sup { 58 | top: -0.5em; 59 | } 60 | img { 61 | border-style: none; 62 | } 63 | button, 64 | input, 65 | optgroup, 66 | select, 67 | textarea { 68 | font-family: inherit; 69 | font-size: 100%; 70 | line-height: 1.15; 71 | margin: 0; 72 | } 73 | button, 74 | input { 75 | overflow: visible; 76 | } 77 | button, 78 | select { 79 | text-transform: none; 80 | } 81 | [type="button"], 82 | [type="reset"], 83 | [type="submit"], 84 | button { 85 | -webkit-appearance: button; 86 | } 87 | [type="button"]::-moz-focus-inner, 88 | [type="reset"]::-moz-focus-inner, 89 | [type="submit"]::-moz-focus-inner, 90 | button::-moz-focus-inner { 91 | border-style: none; 92 | padding: 0; 93 | } 94 | [type="button"]:-moz-focusring, 95 | [type="reset"]:-moz-focusring, 96 | [type="submit"]:-moz-focusring, 97 | button:-moz-focusring { 98 | outline: 1px dotted ButtonText; 99 | } 100 | fieldset { 101 | padding: 0.35em 0.75em 0.625em; 102 | } 103 | legend { 104 | -webkit-box-sizing: border-box; 105 | box-sizing: border-box; 106 | color: inherit; 107 | display: table; 108 | max-width: 100%; 109 | padding: 0; 110 | white-space: normal; 111 | } 112 | progress { 113 | vertical-align: baseline; 114 | } 115 | textarea { 116 | overflow: auto; 117 | } 118 | [type="checkbox"], 119 | [type="radio"] { 120 | -webkit-box-sizing: border-box; 121 | box-sizing: border-box; 122 | padding: 0; 123 | } 124 | [type="number"]::-webkit-inner-spin-button, 125 | [type="number"]::-webkit-outer-spin-button { 126 | height: auto; 127 | } 128 | [type="search"] { 129 | -webkit-appearance: textfield; 130 | outline-offset: -2px; 131 | } 132 | [type="search"]::-webkit-search-decoration { 133 | -webkit-appearance: none; 134 | } 135 | ::-webkit-file-upload-button { 136 | -webkit-appearance: button; 137 | font: inherit; 138 | } 139 | details { 140 | display: block; 141 | } 142 | summary { 143 | display: list-item; 144 | } 145 | [hidden], 146 | template { 147 | display: none; 148 | } 149 | @font-face { 150 | font-family: Material Icons; 151 | font-style: normal; 152 | font-weight: 400; 153 | src: url(fonts/MaterialIcons-Regular.e79bfd88.eot); 154 | src: local("Material Icons"), local("MaterialIcons-Regular"), url(../fonts/MaterialIcons-Regular.570eb838.woff2) format("woff2"), url(../fonts/MaterialIcons-Regular.012cf6a1.woff) format("woff"), 155 | url(fonts/MaterialIcons-Regular.a37b0c01.ttf) format("truetype"); 156 | } 157 | .material-icons { 158 | font-family: Material Icons; 159 | font-weight: 400; 160 | font-style: normal; 161 | font-size: 24px; 162 | display: inline-block; 163 | line-height: 1; 164 | text-transform: none; 165 | letter-spacing: normal; 166 | word-wrap: normal; 167 | white-space: nowrap; 168 | direction: ltr; 169 | -webkit-font-smoothing: antialiased; 170 | text-rendering: optimizeLegibility; 171 | -moz-osx-font-smoothing: grayscale; 172 | -webkit-font-feature-settings: "liga"; 173 | font-feature-settings: "liga"; 174 | } 175 | -------------------------------------------------------------------------------- /filebrowser/static/fonts/MaterialIcons-Regular.570eb838.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jakbin/filebrowser/035e98fe45c052278c5a860feb8b6f5c2113e8fe/filebrowser/static/fonts/MaterialIcons-Regular.570eb838.woff2 -------------------------------------------------------------------------------- /filebrowser/static/js/main.js: -------------------------------------------------------------------------------- 1 | window.onbeforeunload = function(){ 2 | sessionStorage.clear(); 3 | } 4 | sessionStorage.setItem("folder-names",""); 5 | sessionStorage.setItem("select",""); 6 | sessionStorage.setItem("selected-item",""); 7 | sessionStorage.setItem("multiple-selection",""); 8 | sessionStorage.setItem("folder-list-select",""); 9 | sessionStorage.setItem("folder-list-name",""); 10 | 11 | $(document).ready(function(){ 12 | 13 | function unselecte(){ 14 | sessionStorage.setItem("selected-item", ""); 15 | sessionStorage.setItem("select", "") 16 | $("#dropdown").find(".action:lt(4)").remove(); 17 | $(".counter").remove(); 18 | } 19 | 20 | function loaddata(folder, name){ 21 | $("#loading").show(); 22 | $.ajax({ 23 | url : "/load-data", 24 | type : "POST", 25 | data : JSON.stringify({name : name, folder : folder}), 26 | dataType : "json", 27 | contentType : "application/json; charset=utf-8", 28 | complete : function(data){ 29 | $("#loading").hide(); 30 | if (data.status == 200){ 31 | $("#load-data").html(data.responseText); 32 | }else if (data.status == 500){ 33 | console.log(data.responseText) 34 | } 35 | } 36 | }); 37 | } 38 | 39 | var folder = sessionStorage.getItem("folder-names"); 40 | loaddata(folder, ''); 41 | 42 | $(document).on("click","#home, #myfiles", function(e){ 43 | e.preventDefault(); 44 | if (sessionStorage.getItem("select") == "true"){ 45 | unselecte() 46 | } 47 | 48 | if (sessionStorage.getItem("folder-names") != ""){ 49 | loaddata("", ""); 50 | sessionStorage.setItem("folder-names",""); 51 | $("#links").children().remove(); 52 | } 53 | }); 54 | 55 | $(document).on("click","#link", function(e){ 56 | e.preventDefault(); 57 | 58 | if ($(this).attr("href") != sessionStorage.getItem("folder-names")){ 59 | if (sessionStorage.getItem("select") == "true"){ 60 | unselecte() 61 | } 62 | loaddata($(this).attr("href"), ""); 63 | $(this).nextAll().remove(); 64 | sessionStorage.setItem("folder-names",$(this).attr("href")); 65 | 66 | if (sessionStorage.getItem("select") == "true"){ 67 | $("#dropdown").find(".action:lt(4)").remove(); 68 | $(".counter").remove(); 69 | } 70 | } 71 | }); 72 | 73 | $(document).on("click","#view_list", function(e){ 74 | var a = $("#listing").hasClass("mosaic"); 75 | if (a) { 76 | $("#listing").removeClass("mosaic").addClass("list"); 77 | $("#list-icon").text("view_list"); 78 | } else { 79 | $("#listing").removeClass("list").addClass("mosaic"); 80 | $("#list-icon").text("view_module"); 81 | } 82 | }); 83 | 84 | $(document).on("click", "#info", function(e){ 85 | $('#info-modal').show(); 86 | $('.overlay').show(); 87 | if ($('#info-data').html() == '') { 88 | $.ajax({ 89 | url : "/info", 90 | type : "GET", 91 | success : function(data){ 92 | $('#info-data').append('

Display Name: '+data.foldername+'

'+ 93 | '

Last Modified: '+data.lastmd+'

Number of files: '+data.file+'

'+ 94 | '

Number of directories: '+data.folder+'

') 95 | } 96 | 97 | }); 98 | } 99 | }); 100 | 101 | $(document).on("click", ".overlay", function(e){ 102 | $("#close-btn").trigger('click'); 103 | }); 104 | 105 | $(document).on("click", "#close-btn", function(e){ 106 | $('#modal1').hide(); 107 | $("#delete-modal").hide(); 108 | $("#download-modal").hide(); 109 | $("#upload-modal").hide(); 110 | $("#copy-modal").hide(); 111 | $('#info-modal').hide(); 112 | $('.overlay').hide(); 113 | }); 114 | 115 | $(document).on("click", "#new-folder, #new-file, #rename-button", function(e){ 116 | if (sessionStorage.getItem("select") == "true"){ 117 | if ($(this).is('#new-file', '#new-folder')){ 118 | unselecte() 119 | } 120 | } 121 | $('#item-name').val(''); 122 | $('#modal1').show(); 123 | $('.overlay').show(); 124 | if ($(this).is('#new-folder')){ 125 | $('#item-name').focus(); 126 | $('#modal1 div h2').html('New directory'); 127 | $('#modal1 .card-content p').first().html('Write the name of the new directory.'); 128 | $('#modal1 div').children('button').eq('1').html('Create'); 129 | $('#modal1 div').children('button').eq('1').attr('id', 'folder-button'); 130 | }else if ($(this).is('#new-file')){ 131 | $('#item-name').focus(); 132 | $('#modal1 div h2').html('New file'); 133 | $('#modal1 .card-content p').first().html('Write the name of the new file.'); 134 | $('#modal1 div').children('button').eq('1').html('Create'); 135 | $('#modal1 div').children('button').eq('1').attr('id', 'file-button'); 136 | }else{ 137 | $('#modal1 div h2').html('Rename'); 138 | $('#modal1 .card-content p').first().html('Insert a new name for '+''+sessionStorage.getItem("selected-item")+''); 139 | $('#item-name').val(sessionStorage.getItem("selected-item")); 140 | $('#modal1 div').children('button').eq('1').html('Rename'); 141 | $('#modal1 div').children('button').eq('1').attr('id', 'rename'); 142 | } 143 | }); 144 | 145 | $('#item-name').focusin(function(){ 146 | console.log('get here'); 147 | if ($('#item-name').val() !== null){ 148 | $(this).select(); 149 | } 150 | }); 151 | 152 | $(document).on("click","#folder-button", function(e){ 153 | e.preventDefault(); 154 | 155 | var name = $('#item-name').val(); 156 | var folder = sessionStorage.getItem("folder-names"); 157 | 158 | if (name == "") { 159 | // $('#error-message').show(); 160 | // $('#error-message').html("All fields are required !"); 161 | console.log("empty field") 162 | 163 | }else { 164 | 165 | $.ajax({ 166 | url : "/new-folder", 167 | type : "POST", 168 | data : JSON.stringify({name : name, folder : folder}), 169 | dataType : "json", 170 | contentType : "application/json; charset=utf-8", 171 | complete : function(data){ 172 | if (data.responseText == 1){ 173 | loaddata(folder, ""); 174 | // $('#message').show(); 175 | $('#item-name').val(''); 176 | $('#modal1').hide(); 177 | $('.overlay').hide(); 178 | // $('#error-message').html("Data has been Saved !") 179 | console.log("folder created") 180 | }else if (data.responseText != 1 && data.status == 200){ 181 | console.log(data.responseText); 182 | $("#delete-modal").hide(); 183 | }else{ 184 | console.log("unknown error occured"); 185 | } 186 | } 187 | }); 188 | } 189 | }); 190 | 191 | $(document).on("click","#file-button", function(e){ 192 | 193 | var name = $('#item-name').val(); 194 | var folder = sessionStorage.getItem("folder-names"); 195 | 196 | if (name == "") { 197 | // $('#error-message').show(); 198 | // $('#error-message').html("All fields are required !"); 199 | console.log("empty field") 200 | }else { 201 | 202 | $.ajax({ 203 | url : "/new-file", 204 | type : "POST", 205 | data : JSON.stringify({name : name, folder : folder}), 206 | dataType : "json", 207 | contentType : "application/json; charset=utf-8", 208 | complete : function(data){ 209 | if (data.responseText == 1){ 210 | loaddata(folder, ""); 211 | // $('#message').show(); 212 | $('#file-name').val(''); 213 | $('#modal1').hide(); 214 | $('.overlay').hide(); 215 | // $('#error-message').html("Data has been Saved !") 216 | console.log("file created") 217 | }else if (data.responseText != 1 && data.status == 200){ 218 | console.log(data.responseText); 219 | $("#delete-modal").hide(); 220 | }else{ 221 | console.log("unknown error occured"); 222 | } 223 | } 224 | }); 225 | } 226 | }); 227 | 228 | $(document).on("click", "#delete-button", function(e){ 229 | $("#delete-modal").show(); 230 | $('.overlay').show(); 231 | }); 232 | 233 | $(document).on("click","#delete", function(e){ 234 | 235 | if (sessionStorage.getItem("select") == "true"){ 236 | 237 | var name = sessionStorage.getItem("selected-item"); 238 | var folder = sessionStorage.getItem("folder-names"); 239 | 240 | $.ajax({ 241 | url : "/delete", 242 | type : "POST", 243 | data : JSON.stringify({name : name, folder : folder}), 244 | dataType : "json", 245 | contentType : "application/json; charset=utf-8", 246 | complete : function(data){ 247 | if (data.responseText == 1){ 248 | loaddata(folder, ""); 249 | // $('#message').show(); 250 | $("#delete-modal").hide(); 251 | $('.overlay').hide(); 252 | unselecte() 253 | // $('#error-message').html("Data has been Saved !") 254 | console.log("file deleted") 255 | }else if (data.responseText != 1 && data.status == 200){ 256 | console.log(data.responseText); 257 | $("#delete-modal").hide(); 258 | }else{ 259 | console.log("unknown error occured"); 260 | } 261 | } 262 | }); 263 | } 264 | }); 265 | 266 | $(document).on("click","#rename", function(e){ 267 | 268 | if (sessionStorage.getItem("select") == "true"){ 269 | 270 | var name = sessionStorage.getItem("selected-item"); 271 | var folder = sessionStorage.getItem("folder-names"); 272 | var dst = $("#item-name").val(); 273 | 274 | $.ajax({ 275 | url : "/rename", 276 | type : "POST", 277 | data : JSON.stringify({name : name, folder : folder, dst: dst}), 278 | dataType : "json", 279 | contentType : "application/json; charset=utf-8", 280 | complete : function(data){ 281 | if (data.responseText == 1){ 282 | loaddata(folder, ""); 283 | $('#dst-name').val(''); 284 | $("#modal1").hide(); 285 | $('.overlay').hide(); 286 | unselecte() 287 | // $('#error-message').html("Data has been Saved !") 288 | console.log("file renamed") 289 | }else if (data.responseText != 1 && data.status == 200){ 290 | console.log(data.responseText); 291 | $("#delete-modal").hide(); 292 | }else{ 293 | console.log("unknown error occured"); 294 | } 295 | } 296 | }); 297 | } 298 | }); 299 | 300 | $(document).on("click", "#download-button", function(e){ 301 | if (sessionStorage.getItem("select") == "true"){ 302 | var name = sessionStorage.getItem("selected-item"); 303 | var folder = sessionStorage.getItem("folder-names"); 304 | location.href = "/download/"+folder+ name 305 | }else{ 306 | console.log('no item selected') 307 | } 308 | 309 | }); 310 | 311 | $(document).on("click", "#upload-button", function(e){ 312 | $("#upload-modal").show(); 313 | $('.overlay').show(); 314 | }); 315 | 316 | $(document).on("click", "#select-upload-file", function(e){ 317 | $("#file-upload").trigger('click'); 318 | }); 319 | 320 | function uoload(form_data){ 321 | $.ajax({ 322 | url: "/upload", 323 | type: "POST", 324 | data: form_data, 325 | dataType: "json", 326 | contentType: false, 327 | processData: false, 328 | success: function(data){ 329 | if (data == 1){ 330 | loaddata(folder, ""); 331 | $('.overlay').hide(); 332 | $('#upload-modal').hide(); 333 | // $('#file-upload').reset(); 334 | $('#file-upload').val(''); 335 | console.log("file uploaded"); 336 | }else{ 337 | console.log(data); 338 | } 339 | } 340 | }); 341 | } 342 | 343 | $("#file-upload").change(function(e){ 344 | var folder = sessionStorage.getItem("folder-names"); 345 | var form_data = new FormData(); 346 | form_data.append("file1", $("#file-upload")[0].files[0]); 347 | form_data.append('folder', folder); 348 | 349 | uoload(form_data); 350 | }); 351 | 352 | // upload file with drag and drop 353 | var dropZone = document.getElementById('select-upload-file'); 354 | 355 | // Optional. Show the copy icon when dragging over. Seems to only work for chrome. 356 | dropZone.addEventListener('dragover', function(e) { 357 | e.stopPropagation(); 358 | e.preventDefault(); 359 | e.dataTransfer.dropEffect = 'copy'; 360 | }); 361 | 362 | // Get file data on drop 363 | dropZone.addEventListener('drop', function(e) { 364 | e.stopPropagation(); 365 | e.preventDefault(); 366 | 367 | var folder = sessionStorage.getItem("folder-names"); 368 | var form_data = new FormData(); 369 | form_data.append("file1", e.dataTransfer.files[0]); 370 | form_data.append('folder', folder); 371 | 372 | uoload(form_data); 373 | }); 374 | 375 | function folderlist(folder, folderName){ 376 | $("#folder-list").html(''); 377 | $.ajax({ 378 | url : "/folderlist", 379 | type : "POST", 380 | data : JSON.stringify({folder : folder, foldername : folderName}), 381 | dataType : "json", 382 | contentType : "application/json; charset=utf-8", 383 | success : function(data){ 384 | $("#folder-list").append('
  • ..
  • '); 385 | if (data.status != false){ 386 | $.each(data.item, function(key, value){ 387 | $("#folder-list").append('
  • '+ value.path +'
  • '); 388 | }); 389 | }else{ 390 | console.log(data.item); 391 | } 392 | } 393 | }); 394 | } 395 | 396 | $(document).on("click", "#copy-button, #move-button", function(e){ 397 | $("#copy-modal").show(); 398 | $('.overlay').show(); 399 | var folder = sessionStorage.getItem("folder-names"); 400 | $("#folder-list-code").html(folder); 401 | folderlist(folder, ""); 402 | console.log("click on cpmv"); 403 | if ($(this).is('#move-button')){ 404 | console.log("click on mv"); 405 | $('#copy-modal div h2').html('Move'); 406 | $('#copy-modal .card-content p').first().html('Choose the place to move your files:'); 407 | $('#copy-modal div').children('button').eq('1').html('Move'); 408 | $('#copy-modal div').children('button').eq('1').attr('id', 'move-item'); 409 | }else{ 410 | console.log("click on cp"); 411 | $('#copy-modal div h2').html('Copy'); 412 | $('#copy-modal .card-content p').first().html('Choose the place to copy your files:'); 413 | $('#copy-modal div').children('button').eq('1').html('Copy'); 414 | $('#copy-modal div').children('button').eq('1').attr('id', 'copy-item'); 415 | } 416 | }); 417 | 418 | var DELAY = 200, clicks = 0, timer = null; 419 | 420 | $(document).on("click", "li", function(e){ 421 | var $this = $(this); 422 | clicks++; //count clicks 423 | 424 | if(clicks === 1) { 425 | 426 | timer = setTimeout(function() { 427 | 428 | console.log('Single Click folder'); //perform single-click action 429 | if ($this.attr("aria-selected") == "true"){ 430 | $this.removeAttr("aria-selected"); 431 | sessionStorage.setItem("folder-list-select", ""); 432 | sessionStorage.setItem("folder-list-name", ""); 433 | }else{ 434 | $this.attr("aria-selected", true); 435 | if (sessionStorage.getItem("folder-list-select") == "true"){ 436 | $('[aria-label="' + sessionStorage.getItem("folder-list-name") + '"]').removeAttr("aria-selected"); 437 | }else{ 438 | sessionStorage.setItem("folder-list-select", "true"); 439 | } 440 | sessionStorage.setItem("folder-list-name",$this.attr("aria-label")); 441 | } 442 | clicks = 0; //after action performed, reset counter 443 | }, DELAY); 444 | 445 | } else { 446 | 447 | clearTimeout(timer); //prevent single-click action 448 | console.log('Double Click folder'); //perform double-click action 449 | var folderName = $this.attr("aria-label"); 450 | var curFolder = sessionStorage.getItem('folder-names'); 451 | var listFolderName = $("#folder-list-code").html(); 452 | // console.log($("#folder-list-code").html(), folderName); 453 | if (folderName == '..'){ 454 | folderlist(listFolderName, folderName); 455 | var fname = $("#folder-list-code").html(); 456 | var arr = fname.split("/"); 457 | arr.pop(); 458 | arr.pop(); 459 | if (arr.length == 1){ 460 | var foname = arr.join('/'); 461 | $("#folder-list-code").html(foname + '/'); 462 | }else{ 463 | var foname = arr.join('/'); 464 | if (foname == ''){ 465 | $("#folder-list-code").html(''); 466 | }else{ 467 | $("#folder-list-code").html(foname); 468 | } 469 | } 470 | }else{ 471 | console.log(curFolder); 472 | console.log($("#folder-list-code").html()); 473 | console.log(folderName); 474 | folderlist(curFolder+$("#folder-list-code").html(),folderName); 475 | $("#folder-list-code").html($("#folder-list-code").html() + folderName + "/"); 476 | } 477 | clicks = 0; //after action performed, reset counter 478 | } 479 | 480 | }).on("dblclick", function(e){ 481 | e.preventDefault(); //cancel system double-click event 482 | }); 483 | 484 | $(document).on("click", "#close-folder-list", function(e){ 485 | $("#copy-modal").hide(); 486 | $('.overlay').hide(); 487 | $("code").html(''); 488 | }); 489 | 490 | $(document).on("click", "#copy-item, #move-item", function(e){ 491 | var source = sessionStorage.getItem("folder-names"); 492 | var fodestination = $('code').html(); 493 | var destination = sessionStorage.getItem("folder-list-name"); 494 | var itemName = sessionStorage.getItem("selected-item"); 495 | if ($(this).is('#move-item')){ 496 | console.log("click on mv it"); 497 | var url = "/moveItem"; 498 | }else{ 499 | console.log("click on cp it"); 500 | var url = "/copyItem" 501 | } 502 | $.ajax({ 503 | url : url, 504 | type : "POST", 505 | data : JSON.stringify({source : source, itemName : itemName, destination : destination, fodestination : fodestination}), 506 | dataType : "json", 507 | contentType : "application/json; charset=utf-8", 508 | complete : function(data){ 509 | if (data.status == 200){ 510 | $('#copy-modal').hide(); 511 | $('.overlay').hide(); 512 | if (url == '/moveItem'){ 513 | console.log("item moved"); 514 | }else{ 515 | console.log("item copied"); 516 | } 517 | loaddata(source, ""); 518 | unselecte() 519 | sessionStorage.setItem("folder-list-select", ""); 520 | sessionStorage.setItem("folder-list-name", ""); 521 | $("code").html(''); 522 | }else if (data.status == 500){ 523 | console.log("Internal Server Error") 524 | } 525 | } 526 | }); 527 | }); 528 | 529 | }); 530 | -------------------------------------------------------------------------------- /filebrowser/templates/data.html: -------------------------------------------------------------------------------- 1 | {% if folders_data != [] %} 2 |

    Folders

    3 |
    4 | {% for folder, folder_date in folders_data %} 5 |
    6 |
    folder
    7 |
    8 |

    {{ folder }}

    9 |

    10 |

    {{ folder_date }} ago

    11 |
    12 |
    13 | {% endfor %} 14 |
    15 | {% endif %} 16 | {% if files_data != []%} 17 |

    Files

    18 |
    19 | {% for file, file_size, file_date in files_data %} 20 |
    21 |
    insert_drive_file
    22 |
    23 |

    {{ file }}

    24 |

    {{ file_size }}

    25 |

    {{ file_date }} ago

    26 |
    27 |
    28 | {% endfor %} 29 |
    30 | {% endif %} 31 | 32 | {% if files_data == [] and folders_data == [] %} 33 |

    sentiment_dissatisfiedIt feels lonely here...

    34 | {% endif %} -------------------------------------------------------------------------------- /filebrowser/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | FileBrowser 7 | 8 | 9 | 10 | 11 | 12 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
    29 |
    30 |
    31 | 38 |
    39 |
    40 | 45 |
    46 |

    47 |
    48 |
    49 |
    50 | Loading...

    51 |
    52 | 53 |
    54 |
    55 | 56 | 59 | 60 | 61 | 64 | 81 | 84 | 85 |
    86 |
    87 |
    88 |
    89 |
    90 |
    91 |

    Namearrow_upward

    92 |

    Sizearrow_upward

    93 |

    Last modifiedarrow_upward

    94 |
    95 |
    96 |
    97 | 98 |
    99 | 100 | 101 |
    102 |

    Multiple selection enabled

    103 |
    clear
    104 |
    105 |
    106 |
    107 |
    108 |
    109 |
    110 |
    111 |

    New directory

    112 |
    113 |

    Write the name of the new directory.

    114 | 115 |
    116 |
    117 |
    118 | 119 |
    120 |
    121 |

    Are you sure you want to delete this file/folder?

    122 |
    123 |
    124 |
    125 | 126 |
    127 |
    128 |

    Download files

    129 |
    130 |

    Choose the format you want to download.

    131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 |
    139 |
    140 |
    141 |
    142 |

    Upload

    143 |

    Select an option to upload.

    144 |
    145 |
    146 | insert_drive_file 147 |
    File
    148 |
    149 | 150 | 154 | 155 |
    156 |
    157 |
    158 |
    159 |

    160 |
    161 |
    162 |

    163 |
    164 |
      165 |

      Currently navigating on:

      166 |
      167 |
      168 |
      169 |
      170 |
      171 |

      File information

      172 |
      173 |
      174 | 175 |
      176 |
      177 |
      178 | 179 | 180 | 254 | 255 | 256 | -------------------------------------------------------------------------------- /requirements.dev.txt: -------------------------------------------------------------------------------- 1 | -r requirements.txt 2 | 3 | twine 4 | flake8 -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | flask<=2.0 2 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | filebrowser 4 | ======== 5 | 6 | Simple web file browser in python-flask. 7 | 8 | More details on project's README and 9 | `github page `_. 10 | 11 | 12 | Development Version 13 | ------------------- 14 | 15 | The filebrowser development version can be installed by cloning the git 16 | repository from `github`_:: 17 | 18 | git clone git@github.com:jakbin/filebrowser.git 19 | 20 | .. _github: https://github.com/jakbin/filebrowser 21 | 22 | License 23 | ------- 24 | MIT (see LICENSE file). 25 | """ 26 | 27 | from filebrowser import __version__ 28 | 29 | try: 30 | from setuptools import setup 31 | except ImportError: 32 | from distutils.core import setup 33 | 34 | with open("README.md", "r", encoding="utf-8") as readme_file: 35 | readme = readme_file.read() 36 | 37 | setup( 38 | name="filebrowser", 39 | version=__version__, 40 | url="https://github.com/jakbin/filebrowser", 41 | license="MIT License", 42 | author="jakbin", 43 | description="Simple web file browser", 44 | long_description=readme, 45 | long_description_content_type="text/markdown", 46 | classifiers=[ 47 | 'Development Status :: 4 - Beta', 48 | 'License :: OSI Approved :: MIT License', 49 | 'Operating System :: OS Independent', 50 | 'Programming Language :: Python', 51 | 'Programming Language :: Python :: 3', 52 | ], 53 | keywords=['filebrowser', 'web', 'file', 'browser', 'web browser'], 54 | packages=[ 55 | 'filebrowser', 56 | ], 57 | entry_points={ 58 | 'console_scripts': ( 59 | 'filebrowser=filebrowser.main:main' 60 | ) 61 | }, 62 | package_data={ 63 | 'filebrowser': [ 64 | 'templates/*', 65 | 'static/fonts/*', 66 | 'static/js/*', 67 | 'static/css/*', 68 | ]}, 69 | install_requires=['flask<=2.0'], 70 | zip_safe=False, 71 | platforms='any' 72 | ) 73 | --------------------------------------------------------------------------------