Refactorings based on Commit comments
This commit is contained in:
parent
d719e3cdbf
commit
3458f9af43
6 changed files with 242 additions and 230 deletions
|
|
@ -391,12 +391,12 @@ class FileManager(object):
|
|||
self._storage(destination).remove_file(path)
|
||||
eventManager().fire(Events.UPDATED_FILES, dict(type="printables"))
|
||||
|
||||
def copy_file(self, destination, source, dst, allow_overwrite=False):
|
||||
self._storage(destination).copy_file(source, dst, allow_overwrite)
|
||||
def copy_file(self, destination, source, dst):
|
||||
self._storage(destination).copy_file(source, dst)
|
||||
eventManager().fire(Events.UPDATED_FILES, dict(type="printables"))
|
||||
|
||||
def move_file(self, destination, source, dst, allow_overwrite=False):
|
||||
self._storage(destination).move_file(source, dst, allow_overwrite)
|
||||
def move_file(self, destination, source, dst):
|
||||
self._storage(destination).move_file(source, dst)
|
||||
eventManager().fire(Events.UPDATED_FILES, dict(type="printables"))
|
||||
|
||||
def add_folder(self, destination, path, ignore_existing=True):
|
||||
|
|
@ -412,8 +412,8 @@ class FileManager(object):
|
|||
self._storage(destination).copy_folder(source, dst)
|
||||
eventManager().fire(Events.UPDATED_FILES, dict(type="printables"))
|
||||
|
||||
def move_folder(self, destination, source, dst, allow_overwrite=False):
|
||||
self._storage(destination).move_folder(source, dst, allow_overwrite)
|
||||
def move_folder(self, destination, source, dst):
|
||||
self._storage(destination).move_folder(source, dst)
|
||||
eventManager().fire(Events.UPDATED_FILES, dict(type="printables"))
|
||||
|
||||
def get_metadata(self, destination, path):
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ class StorageInterface(object):
|
|||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def move_folder(self, source, destination, allow_overwrite=False):
|
||||
def move_folder(self, source, destination):
|
||||
"""
|
||||
Moves the folder ``source`` to ``destination``
|
||||
|
||||
|
|
@ -172,7 +172,7 @@ class StorageInterface(object):
|
|||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def copy_file(self, source, destination, allow_overwrite=False):
|
||||
def copy_file(self, source, destination):
|
||||
"""
|
||||
Copys the file ``source`` to ``destination``
|
||||
|
||||
|
|
@ -181,7 +181,7 @@ class StorageInterface(object):
|
|||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def move_file(self, source, destination, allow_overwrite=False):
|
||||
def move_file(self, source, destination):
|
||||
"""
|
||||
Moves the file ``source`` to ``destination``
|
||||
|
||||
|
|
@ -429,6 +429,9 @@ class LocalFileStorage(StorageInterface):
|
|||
yield self.join_path(entry, sub_entry[0]), sub_entry[1], sub_entry[2]
|
||||
|
||||
def file_in_path(self, path, filepath):
|
||||
filepath = self.sanitize_path(filepath)
|
||||
path = self.sanitize_path(path)
|
||||
|
||||
return filepath.startswith(path)
|
||||
|
||||
def file_exists(self, path):
|
||||
|
|
@ -476,45 +479,69 @@ class LocalFileStorage(StorageInterface):
|
|||
import shutil
|
||||
shutil.rmtree(folder_path)
|
||||
|
||||
def _copyMove1(self, source, destination):
|
||||
sourcepath, sourcename = self.sanitize(source)
|
||||
destinationpath, destinationname = self.sanitize(destination)
|
||||
|
||||
source_path = os.path.join(sourcepath, sourcename)
|
||||
if not os.path.exists(source_path):
|
||||
raise RuntimeError("{sourcename} in {sourcepath} does not exist".format(**locals()))
|
||||
|
||||
destination_path = os.path.join(destinationpath, destinationname)
|
||||
if os.path.exists(destination_path):
|
||||
raise RuntimeError("{destinationname} does already exist in {destinationpath}".format(**locals()))
|
||||
|
||||
sourceObj = dict(
|
||||
path=sourcepath,
|
||||
name=sourcename,
|
||||
fullpath=source_path,
|
||||
)
|
||||
destinationObj = dict(
|
||||
path=destinationpath,
|
||||
name=destinationname,
|
||||
fullpath=destination_path,
|
||||
)
|
||||
return sourceObj, destinationObj
|
||||
|
||||
def _copyMove2(self, source, destination):
|
||||
sourceObj, destinationObj = self._copyMove1(source, destination)
|
||||
|
||||
if not os.path.isfile(sourceObj["fullpath"]):
|
||||
raise RuntimeError("%s in %s is not a file" % (sourceObj["name"], sourceObj["path"]))
|
||||
|
||||
sourcemetadata = self._get_metadata(sourceObj["path"])
|
||||
if not sourcemetadata:
|
||||
sourcemetadata = dict()
|
||||
|
||||
destinationmetadata = self._get_metadata(destinationObj["path"])
|
||||
if not destinationmetadata:
|
||||
destinationmetadata = dict()
|
||||
|
||||
sourceObj.update(dict(metadata=sourcemetadata))
|
||||
destinationObj.update(dict(metadata=destinationmetadata))
|
||||
return sourceObj, destinationObj
|
||||
|
||||
def copy_folder(self, source, destination):
|
||||
sourcepath, sourcename = self.sanitize(source)
|
||||
destinationpath, destinationname = self.sanitize(destination)
|
||||
sourceObj, destinationObj = self._copyMove1(source, destination)
|
||||
|
||||
sourcefolder_path = os.path.join(sourcepath, sourcename)
|
||||
if not os.path.exists(sourcefolder_path):
|
||||
return
|
||||
|
||||
if not os.path.isdir(sourcefolder_path):
|
||||
raise RuntimeError("{name} in {path} is not a folder".format(**locals()))
|
||||
|
||||
destinationfolder_path = os.path.join(destinationpath, destinationname)
|
||||
if os.path.exists(destinationfolder_path):
|
||||
raise RuntimeError("{newname} does already exist in {newpath}".format(**locals()))
|
||||
if not os.path.isdir(sourceObj["fullpath"]):
|
||||
raise RuntimeError("%s in %s is not a folder" % (sourceObj["name"], sourceObj["path"]))
|
||||
|
||||
try:
|
||||
shutil.copytree(sourcefolder_path, destinationfolder_path)
|
||||
shutil.copytree(sourceObj["fullpath"], destinationObj["fullpath"])
|
||||
except Exception as e:
|
||||
raise RuntimeError("Could not copy {oldname} in {oldpath} to {newname} in {newpath}".format(**locals()), e)
|
||||
raise RuntimeError("Could not copy %s in %s to %s in %s" % (sourceObj["name"], sourceObj["path"], destinationObj["name"], destinationObj["path"]), e)
|
||||
|
||||
def move_folder(self, source, destination, allow_overwrite=False):
|
||||
sourcepath, sourcename = self.sanitize(source)
|
||||
destinationpath, destinationname = self.sanitize(destination)
|
||||
def move_folder(self, source, destination):
|
||||
sourceObj, destinationObj = self._copyMove1(source, destination)
|
||||
|
||||
sourcefolder_path = os.path.join(sourcepath, sourcename)
|
||||
if not os.path.exists(sourcefolder_path):
|
||||
return
|
||||
|
||||
if not os.path.isdir(sourcefolder_path):
|
||||
raise RuntimeError("{name} in {path} is not a folder".format(**locals()))
|
||||
|
||||
destinationfolder_path = os.path.join(destinationpath, destinationname)
|
||||
if os.path.exists(destinationfolder_path) and not allow_overwrite:
|
||||
raise RuntimeError("{newname} does already exist in {newpath} and overwriting is prohibited".format(**locals()))
|
||||
if not os.path.isdir(sourceObj["fullpath"]):
|
||||
raise RuntimeError("%s in %s is not a folder" % (sourceObj["name"], sourceObj["path"]))
|
||||
|
||||
try:
|
||||
shutil.move(sourcefolder_path, destinationfolder_path)
|
||||
shutil.move(sourceObj["fullpath"], destinationObj["fullpath"])
|
||||
except Exception as e:
|
||||
raise RuntimeError("Could not move {oldname} in {oldpath} to {newname} in {newpath}".format(**locals()), e)
|
||||
raise RuntimeError("Could not move %s in %s to %s in %s" % (sourceObj["name"], sourceObj["path"], destinationObj["name"], destinationObj["path"]), e)
|
||||
|
||||
def add_file(self, path, file_object, printer_profile=None, links=None, allow_overwrite=False):
|
||||
path, name = self.sanitize(path)
|
||||
|
|
@ -585,83 +612,41 @@ class LocalFileStorage(StorageInterface):
|
|||
if not "links" in m:
|
||||
continue
|
||||
for link in m["links"]:
|
||||
if "rel" in link and "hash" in link and (link["rel"] == "model" or link["rel"] == "machinecode") and link["hash"] == hash:
|
||||
if "rel" in link and "hash" in link and (
|
||||
link["rel"] == "model" or link["rel"] == "machinecode") and link["hash"] == hash:
|
||||
m["links"].remove(link)
|
||||
del metadata[name]
|
||||
self._save_metadata(path, metadata)
|
||||
|
||||
def copy_file(self, source, destination, allow_overwrite=False):
|
||||
sourcepath, sourcename = self.sanitize(source)
|
||||
destinationpath, destinationname = self.sanitize(destination)
|
||||
|
||||
oldmetadata = self._get_metadata(sourcepath)
|
||||
if not oldmetadata:
|
||||
oldmetadata = dict()
|
||||
|
||||
newmetadata = self._get_metadata(destinationpath)
|
||||
if not newmetadata:
|
||||
newmetadata = dict()
|
||||
|
||||
sourcefile_path = os.path.join(sourcepath, sourcename)
|
||||
if not os.path.exists(sourcefile_path):
|
||||
return
|
||||
|
||||
if not os.path.isfile(sourcefile_path):
|
||||
raise RuntimeError("{oldname} in {oldpath} is not a file".format(**locals()))
|
||||
|
||||
destinationfile_path = os.path.join(destinationpath, destinationname)
|
||||
if os.path.exists(destinationfile_path) and not allow_overwrite:
|
||||
raise RuntimeError("{newname} does already exist in {newpath} and overwriting is prohibited".format(**locals()))
|
||||
def copy_file(self, source, destination):
|
||||
sourceObj, destinationObj = self._copyMove2(source, destination)
|
||||
|
||||
try:
|
||||
shutil.copy2(sourcefile_path, destinationfile_path)
|
||||
shutil.copy2(sourceObj["fullpath"], destinationObj["fullpath"])
|
||||
except Exception as e:
|
||||
raise RuntimeError("Could not copy {oldname} in {oldpath} to {newname} in {newpath}".format(**locals()), e)
|
||||
raise RuntimeError("Could not copy %s in %s to %s in %s" % (sourceObj["name"], sourceObj["path"], destinationObj["name"], destinationObj["path"]), e)
|
||||
|
||||
if sourcename in oldmetadata:
|
||||
metadata = oldmetadata[sourcename]
|
||||
|
||||
newmetadata[destinationname] = metadata
|
||||
newmetadata[destinationname]["hash"] = self._create_hash(destinationfile_path)
|
||||
self._save_metadata(destinationpath, newmetadata)
|
||||
if sourceObj["name"] in sourceObj["metadata"]:
|
||||
destinationObj["metadata"][destinationObj["name"]] = sourceObj["metadata"][sourceObj["name"]]
|
||||
destinationObj["metadata"][destinationObj["name"]]["hash"] = self._create_hash(destinationObj["fullpath"])
|
||||
self._save_metadata(destinationObj["path"], destinationObj["metadata"])
|
||||
|
||||
def move_file(self, source, destination, allow_overwrite=False):
|
||||
sourcepath, sourcename = self.sanitize(source)
|
||||
destinationpath, destinationname = self.sanitize(destination)
|
||||
|
||||
oldmetadata = self._get_metadata(sourcepath)
|
||||
if not oldmetadata:
|
||||
oldmetadata = dict()
|
||||
|
||||
newmetadata = self._get_metadata(destinationpath)
|
||||
if not newmetadata:
|
||||
newmetadata = dict()
|
||||
|
||||
sourcefile_path = os.path.join(sourcepath, sourcename)
|
||||
if not os.path.exists(sourcefile_path):
|
||||
return
|
||||
|
||||
if not os.path.isfile(sourcefile_path):
|
||||
raise RuntimeError("{oldname} in {oldpath} is not a file".format(**locals()))
|
||||
|
||||
destinationfile_path = os.path.join(destinationpath, destinationname)
|
||||
if os.path.exists(destinationfile_path) and not allow_overwrite:
|
||||
raise RuntimeError("{newname} does already exist in {newpath} and overwriting is prohibited".format(**locals()))
|
||||
sourceObj, destinationObj = self._copyMove2(source, destination)
|
||||
|
||||
try:
|
||||
shutil.move(sourcefile_path, destinationfile_path)
|
||||
shutil.move(sourceObj["fullpath"], destinationObj["fullpath"])
|
||||
except Exception as e:
|
||||
raise RuntimeError("Could not move {oldname} in {oldpath} to {newname} in {newpath}".format(**locals()), e)
|
||||
raise RuntimeError("Could not move %s in %s to %s in %s" % (sourceObj["name"], sourceObj["path"], destinationObj["name"], destinationObj["path"]), e)
|
||||
|
||||
if sourcename in oldmetadata:
|
||||
metadata = oldmetadata[sourcename]
|
||||
del oldmetadata[sourcename]
|
||||
self._save_metadata(sourcepath, oldmetadata)
|
||||
|
||||
newmetadata[destinationname] = metadata
|
||||
newmetadata[destinationname]["hash"] = self._create_hash(destinationfile_path)
|
||||
self._save_metadata(destinationpath, newmetadata)
|
||||
if sourceObj["name"] in sourceObj["metadata"]:
|
||||
metadata = sourceObj["metadata"][sourceObj["name"]]
|
||||
del sourceObj["metadata"][sourceObj["name"]]
|
||||
self._save_metadata(sourceObj["path"], sourceObj["metadata"])
|
||||
|
||||
destinationObj["metadata"][destinationObj["name"]] = metadata
|
||||
destinationObj["metadata"][destinationObj["name"]]["hash"] = self._create_hash(destinationObj["fullpath"])
|
||||
self._save_metadata(destinationObj["path"], destinationObj["metadata"])
|
||||
|
||||
def get_metadata(self, path):
|
||||
path, name = self.sanitize(path)
|
||||
|
|
@ -1160,25 +1145,18 @@ class LocalFileStorage(StorageInterface):
|
|||
)
|
||||
|
||||
if not filter or filter(entry, entry_data):
|
||||
def get_size(start_path):
|
||||
def get_size():
|
||||
total_size = 0
|
||||
for root, dirs, files in os.walk(start_path):
|
||||
for f in files:
|
||||
if f is ".metadata.yaml":
|
||||
continue
|
||||
|
||||
fp = os.path.join(root, f)
|
||||
total_size += os.path.getsize(fp)
|
||||
for element in entry_data["children"].itervalues():
|
||||
if "size" in element:
|
||||
total_size += element["size"]
|
||||
|
||||
return total_size
|
||||
|
||||
# only add folders passing the optional filter
|
||||
extended_entry_data = dict()
|
||||
extended_entry_data.update(entry_data)
|
||||
extended_entry_data["size"] = get_size(entry_path)
|
||||
stat = os.stat(entry_path)
|
||||
if stat:
|
||||
extended_entry_data["date"] = int(stat.st_ctime)
|
||||
extended_entry_data["size"] = get_size()
|
||||
|
||||
result[entry] = extended_entry_data
|
||||
|
||||
|
|
|
|||
|
|
@ -25,13 +25,8 @@ import psutil
|
|||
|
||||
@api.route("/files", methods=["GET"])
|
||||
def readGcodeFiles():
|
||||
filter = None
|
||||
recursive = False
|
||||
if "filter" in request.values:
|
||||
filter = request.values["filter"]
|
||||
|
||||
if "recursive" in request.values:
|
||||
recursive = request.values["recursive"] == 'true'
|
||||
filter = "filter" in request.values and request.values["recursive"] in valid_boolean_trues
|
||||
recursive = "recursive" in request.values and request.values["recursive"] in valid_boolean_trues
|
||||
|
||||
files = _getFileList(FileDestinations.LOCAL, filter=filter, recursive=recursive)
|
||||
files.extend(_getFileList(FileDestinations.SDCARD))
|
||||
|
|
@ -62,17 +57,40 @@ def _getFileDetails(origin, path):
|
|||
files = _getFileList(origin, recursive=True)
|
||||
path = path.split('/')
|
||||
|
||||
def recursive_get_filedetails(files, path):
|
||||
for file in files:
|
||||
if file["name"] == path[0]:
|
||||
if len(path) > 1:
|
||||
return recursive_get_filedetails(file["children"], path[1:])
|
||||
else:
|
||||
return file
|
||||
if len(path) == 1:
|
||||
# shortcut for files in the root folder
|
||||
name = path[0]
|
||||
for f in files:
|
||||
if f["name"] == name:
|
||||
return f
|
||||
|
||||
return None
|
||||
|
||||
return recursive_get_filedetails(files, path)
|
||||
node = files
|
||||
while path:
|
||||
segment = path.pop(0)
|
||||
for f in node:
|
||||
if not f["name"] == segment:
|
||||
# wrong name => next!
|
||||
continue
|
||||
|
||||
if not path:
|
||||
# no path left and name matches => found it!
|
||||
return f
|
||||
|
||||
if not f["type"] == "folder":
|
||||
# path left but not a folder => that doesn't work
|
||||
return None
|
||||
|
||||
# we'll use this folder's children as the next iteration
|
||||
node = f["children"]
|
||||
break
|
||||
else:
|
||||
# nothing matched the name, we can't find it
|
||||
return None
|
||||
|
||||
# nothing returned until now => not found
|
||||
return None
|
||||
|
||||
|
||||
def _getFileList(origin, filter=None, recursive=False):
|
||||
|
|
@ -100,52 +118,55 @@ def _getFileList(origin, filter=None, recursive=False):
|
|||
|
||||
files = fileManager.list_files(origin, filter=filter_func, recursive=recursive)[origin].values()
|
||||
|
||||
def recursive_analysis(files, path):
|
||||
def analyse_recursively(files, path=None):
|
||||
if path is None:
|
||||
path = ""
|
||||
|
||||
for file in files:
|
||||
file["origin"] = FileDestinations.LOCAL
|
||||
|
||||
if file["type"] == "folder":
|
||||
file["children"] = recursive_analysis(file["children"].values(), path + file["name"] + "/")
|
||||
file["children"] = analyse_recursively(file["children"].values(), path + file["name"] + "/")
|
||||
else:
|
||||
if "analysis" in file and octoprint.filemanager.valid_file_type(file["name"], type="gcode"):
|
||||
file["gcodeAnalysis"] = file["analysis"]
|
||||
del file["analysis"]
|
||||
|
||||
if "analysis" in file and octoprint.filemanager.valid_file_type(file["name"], type="gcode"):
|
||||
file["gcodeAnalysis"] = file["analysis"]
|
||||
del file["analysis"]
|
||||
|
||||
if "history" in file and octoprint.filemanager.valid_file_type(file["name"], type="gcode"):
|
||||
# convert print log
|
||||
history = file["history"]
|
||||
del file["history"]
|
||||
success = 0
|
||||
failure = 0
|
||||
last = None
|
||||
for entry in history:
|
||||
success += 1 if "success" in entry and entry["success"] else 0
|
||||
failure += 1 if "success" in entry and not entry["success"] else 0
|
||||
if not last or ("timestamp" in entry and "timestamp" in last and entry["timestamp"] > last["timestamp"]):
|
||||
last = entry
|
||||
if last:
|
||||
prints = dict(
|
||||
success=success,
|
||||
failure=failure,
|
||||
last=dict(
|
||||
success=last["success"],
|
||||
date=last["timestamp"]
|
||||
if "history" in file and octoprint.filemanager.valid_file_type(file["name"], type="gcode"):
|
||||
# convert print log
|
||||
history = file["history"]
|
||||
del file["history"]
|
||||
success = 0
|
||||
failure = 0
|
||||
last = None
|
||||
for entry in history:
|
||||
success += 1 if "success" in entry and entry["success"] else 0
|
||||
failure += 1 if "success" in entry and not entry["success"] else 0
|
||||
if not last or ("timestamp" in entry and "timestamp" in last and entry["timestamp"] > last["timestamp"]):
|
||||
last = entry
|
||||
if last:
|
||||
prints = dict(
|
||||
success=success,
|
||||
failure=failure,
|
||||
last=dict(
|
||||
success=last["success"],
|
||||
date=last["timestamp"]
|
||||
)
|
||||
)
|
||||
)
|
||||
if "printTime" in last:
|
||||
prints["last"]["printTime"] = last["printTime"]
|
||||
file["prints"] = prints
|
||||
if "printTime" in last:
|
||||
prints["last"]["printTime"] = last["printTime"]
|
||||
file["prints"] = prints
|
||||
|
||||
file.update({
|
||||
"refs": {
|
||||
"resource": url_for(".readGcodeFile", target=FileDestinations.LOCAL, filename=path + file["name"], _external=True),
|
||||
"download": url_for("index", _external=True) + "downloads/files/" + FileDestinations.LOCAL + "/" + path + file["name"]
|
||||
}
|
||||
})
|
||||
file.update({
|
||||
"refs": {
|
||||
"resource": url_for(".readGcodeFile", target=FileDestinations.LOCAL, filename=path + file["name"], _external=True),
|
||||
"download": url_for("index", _external=True) + "downloads/files/" + FileDestinations.LOCAL + "/" + path + file["name"]
|
||||
}
|
||||
})
|
||||
|
||||
return files
|
||||
|
||||
files = recursive_analysis(files, "")
|
||||
analyse_recursively(files)
|
||||
|
||||
return files
|
||||
|
||||
|
|
@ -164,13 +185,17 @@ def _verifyFolderExists(origin, foldername):
|
|||
return fileManager.folder_exists(origin, foldername)
|
||||
|
||||
|
||||
def _verifyFolderNotBusy(target, foldername):
|
||||
def _isBusy(target, path):
|
||||
currentOrigin, currentFilename = _getCurrentFile()
|
||||
if currentFilename is not None and fileManager.file_in_path(target, path, currentFilename) and currentOrigin == target and (printer.is_printing() or printer.is_paused()):
|
||||
return True
|
||||
|
||||
busy_files = fileManager.get_busy_files()
|
||||
for item in busy_files:
|
||||
if target == item[0] and fileManager.file_in_path(target, foldername, item[1]):
|
||||
return False
|
||||
if target == item[0] and fileManager.file_in_path(target, path, item[1]):
|
||||
return True
|
||||
|
||||
return True
|
||||
return False
|
||||
|
||||
@api.route("/files/<string:target>", methods=["POST"])
|
||||
@restricted_access
|
||||
|
|
@ -312,14 +337,13 @@ def uploadGcodeFile(target):
|
|||
r = make_response(jsonify(files=files, done=done), 201)
|
||||
r.headers["Location"] = location
|
||||
return r
|
||||
else:
|
||||
if "foldername" not in request.json:
|
||||
return make_response("No path information or no file included", 409)
|
||||
elif "foldername" in request.values:
|
||||
foldername = request.values["foldername"]
|
||||
|
||||
if not target in [FileDestinations.LOCAL]:
|
||||
return make_response("Unknown target: %s" % target, 404)
|
||||
return make_response("Unknown target: %s" % target, 400)
|
||||
|
||||
futurePath, futureName = fileManager.sanitize(target, request.json["foldername"])
|
||||
futurePath, futureName = fileManager.sanitize(target, foldername)
|
||||
futureFullPath = fileManager.join_path(target, futurePath, futureName)
|
||||
if octoprint.filemanager.valid_file_type(futureName):
|
||||
return make_response("Can't create a folder named %s, please try another name" % futureName, 409)
|
||||
|
|
@ -327,6 +351,8 @@ def uploadGcodeFile(target):
|
|||
added_folder = fileManager.add_folder(target, futureFullPath)
|
||||
if added_folder is None:
|
||||
return make_response("Could not create folder %s" % futureName, 500)
|
||||
else:
|
||||
return make_response("No file to upload and no folder to create", 400)
|
||||
|
||||
return NO_CONTENT
|
||||
|
||||
|
|
@ -496,44 +522,37 @@ def gcodeFileCommand(filename, target):
|
|||
elif command == "copy" or command == "move":
|
||||
# Copy and move are only possible on local storage
|
||||
if not target in [FileDestinations.LOCAL]:
|
||||
return make_response("Unknown target: %s" % target, 404)
|
||||
return make_response("Unsupported target for {}: {}".format(command, target), 400)
|
||||
|
||||
if not _verifyFileExists(target, filename) and not _verifyFolderExists(target, filename):
|
||||
return make_response("File/Folder not found on '%s': %s" % (target, filename), 404)
|
||||
|
||||
overwrite = data["overwrite"] if "overwrite" in data else False
|
||||
destination = data["destination"]
|
||||
|
||||
if _verifyFolderExists(target, destination):
|
||||
path, name = fileManager.split_path(target, filename)
|
||||
destination = fileManager.join_path(target, destination, name)
|
||||
|
||||
if fileManager.file_exists(target, destination) and not overwrite:
|
||||
return make_response("File already exists and overwrite is prohibited: %s" % filename, 409)
|
||||
if _verifyFileExists(target, destination) or _verifyFolderExists(target, destination):
|
||||
return make_response("File/Folder already exists: %s" % filename, 409)
|
||||
|
||||
if command == "copy":
|
||||
if fileManager.file_exists(target, filename):
|
||||
fileManager.copy_file(target, filename, destination, overwrite)
|
||||
fileManager.copy_file(target, filename, destination)
|
||||
elif fileManager.folder_exists(target, filename):
|
||||
fileManager.copy_folder(target, filename, destination)
|
||||
elif command == "move":
|
||||
# prohibit deleting or moving files that are currently in use
|
||||
currentOrigin, currentFilename = _getCurrentFile()
|
||||
|
||||
if currentFilename is not None and fileManager.file_in_path(target, filename, currentFilename) and currentOrigin == target and (printer.is_printing() or printer.is_paused()):
|
||||
return make_response("Trying to delete a folder that contains a file that is currently being printed: %s" % filename, 409)
|
||||
|
||||
if not _verifyFolderNotBusy(target, filename):
|
||||
return make_response("Trying to delete a folder that contains a file that is currently in use: %s" % filename, 409)
|
||||
if _isBusy(target, filename):
|
||||
return make_response("Trying to move a file/folder that is currently in use: %s" % filename, 409)
|
||||
|
||||
# deselect the file if it's currently selected
|
||||
currentOrigin, currentFilename = _getCurrentFile()
|
||||
if currentFilename is not None and filename == currentFilename:
|
||||
printer.unselect_file()
|
||||
|
||||
if fileManager.file_exists(target, filename):
|
||||
fileManager.move_file(target, filename, destination, overwrite)
|
||||
fileManager.move_file(target, filename, destination)
|
||||
elif fileManager.folder_exists(target, filename):
|
||||
fileManager.move_folder(target, filename, destination, overwrite)
|
||||
fileManager.move_folder(target, filename, destination)
|
||||
|
||||
return NO_CONTENT
|
||||
|
||||
|
|
@ -546,18 +565,13 @@ def deleteGcodeFile(filename, target):
|
|||
|
||||
if _verifyFileExists(target, filename):
|
||||
if not target in [FileDestinations.LOCAL, FileDestinations.SDCARD]:
|
||||
return make_response("Unknown target: %s" % target, 404)
|
||||
return make_response("Unknown target: %s" % target, 400)
|
||||
|
||||
# prohibit deleting files that are currently in use
|
||||
currentOrigin, currentFilename = _getCurrentFile()
|
||||
|
||||
if currentFilename is not None and currentFilename == filename and currentOrigin == target and (printer.is_printing() or printer.is_paused()):
|
||||
return make_response("Trying to delete file that is currently being printed: %s" % filename, 409)
|
||||
|
||||
if not _verifyFolderNotBusy(target, filename):
|
||||
if _isBusy(target, filename):
|
||||
return make_response("Trying to delete a file that is currently in use: %s" % filename, 409)
|
||||
|
||||
# deselect the file if it's currently selected
|
||||
currentOrigin, currentFilename = _getCurrentFile()
|
||||
if currentFilename is not None and filename == currentFilename:
|
||||
printer.unselect_file()
|
||||
|
||||
|
|
@ -569,19 +583,14 @@ def deleteGcodeFile(filename, target):
|
|||
|
||||
elif _verifyFolderExists(target, filename):
|
||||
if not target in [FileDestinations.LOCAL]:
|
||||
return make_response("Unknown target: %s" % target, 404)
|
||||
return make_response("Unknown target: %s" % target, 400)
|
||||
|
||||
folderpath = filename
|
||||
# prohibit deleting folders that are currently in use
|
||||
currentOrigin, currentFilename = _getCurrentFile()
|
||||
|
||||
if currentFilename is not None and fileManager.file_in_path(target, folderpath, currentFilename) and currentOrigin == target and (printer.is_printing() or printer.is_paused()):
|
||||
return make_response("Trying to delete a folder that contains a file that is currently being printed: %s" % folderpath, 409)
|
||||
|
||||
if not _verifyFolderNotBusy(target, folderpath):
|
||||
if _isBusy(target, folderpath):
|
||||
return make_response("Trying to delete a folder that contains a file that is currently in use: %s" % folderpath, 409)
|
||||
|
||||
# deselect the file if it's currently selected
|
||||
currentOrigin, currentFilename = _getCurrentFile()
|
||||
if currentFilename is not None and fileManager.file_in_path(target, folderpath, currentFilename):
|
||||
printer.unselect_file()
|
||||
|
||||
|
|
|
|||
|
|
@ -47,11 +47,13 @@
|
|||
get: getFile,
|
||||
|
||||
list: function (opts) {
|
||||
return OctoPrint.get(url, opts).done(preProcessList);
|
||||
return OctoPrint.get(url, opts)
|
||||
.done(preProcessList);
|
||||
},
|
||||
|
||||
listForLocation: function (location, opts) {
|
||||
return OctoPrint.get(resourceForLocation(location), opts).done(preProcessList);
|
||||
return OctoPrint.get(resourceForLocation(location), opts)
|
||||
.done(preProcessList);
|
||||
},
|
||||
|
||||
select: function (location, filename, print, opts) {
|
||||
|
|
@ -73,6 +75,23 @@
|
|||
return OctoPrint.delete(resourceForFile(location, filename), opts);
|
||||
},
|
||||
|
||||
copy: function(location, filename, destination, opts) {
|
||||
return issueFileCommand(location, filename, "copy", { destination: destination }, opts);
|
||||
},
|
||||
|
||||
move: function(location, filename, destination, opts) {
|
||||
return issueFileCommand(location, filename, "move", { destination: destination }, opts);
|
||||
},
|
||||
|
||||
createFolder: function (location, name, path) {
|
||||
var data = "foldername=" + name;
|
||||
if (path != undefined && path != "") {
|
||||
data = "foldername:" + path + "/" + name;
|
||||
}
|
||||
|
||||
return OctoPrint.post(resourceForLocation(location), data);
|
||||
},
|
||||
|
||||
upload: function (location, file, data) {
|
||||
data = data || {};
|
||||
|
||||
|
|
|
|||
|
|
@ -99,10 +99,7 @@ $(function() {
|
|||
return data["type"] && (data["type"] == "model" || data["type"] == "folder");
|
||||
},
|
||||
"emptyFolder": function(data) {
|
||||
if (data["type"] && data["type"] != "folder")
|
||||
return true;
|
||||
|
||||
return data.children.length != 0;
|
||||
return data["type"] && (data["type"] != "folder" || data["children"].length != 0);
|
||||
}
|
||||
},
|
||||
"name",
|
||||
|
|
@ -115,6 +112,7 @@ $(function() {
|
|||
var filter = function(data) { return data["type"] && data["type"] == "folder"; };
|
||||
return _.filter(self.listHelper.paginatedItems(), filter);
|
||||
});
|
||||
|
||||
self.filesOnlyList = ko.dependentObservable(function() {
|
||||
var filter = function(data) { return data["type"] && data["type"] != "folder"; };
|
||||
return _.filter(self.listHelper.paginatedItems(), filter);
|
||||
|
|
@ -215,6 +213,7 @@ $(function() {
|
|||
self.currentPath(OctoPrint.files.pathForElement(data));
|
||||
self.listHelper.updateItems(data.children);
|
||||
};
|
||||
|
||||
self.changeFolderByPath = function(path) {
|
||||
var element = OctoPrint.files.elementByPath(path, { children: self.allItems() });
|
||||
if (element) {
|
||||
|
|
@ -245,15 +244,18 @@ $(function() {
|
|||
}
|
||||
|
||||
var index = self.listHelper.paginatedItems().indexOf(file) + 1;
|
||||
if (index >= self.listHelper.paginatedItems().length)
|
||||
if (index >= self.listHelper.paginatedItems().length) {
|
||||
index = index - 2;
|
||||
if (index < 0)
|
||||
}
|
||||
if (index < 0) {
|
||||
index = 0;
|
||||
}
|
||||
|
||||
var filenameToFocus = undefined;
|
||||
var fileToFocus = self.listHelper.paginatedItems()[index];
|
||||
if (fileToFocus)
|
||||
if (fileToFocus) {
|
||||
filenameToFocus = fileToFocus.name;
|
||||
}
|
||||
|
||||
OctoPrint.files.delete(file.origin, OctoPrint.files.pathForElement(file))
|
||||
.done(function() {
|
||||
|
|
|
|||
|
|
@ -7,25 +7,27 @@
|
|||
<!-- /ko -->
|
||||
|
||||
<!-- ko if: listStyle() == 'folders_files' -->
|
||||
<!-- ko slimScrolledForeach: foldersOnlyList -->
|
||||
<div class="entry" data-bind="attr: { id: $root.getEntryId($data) }, template: { name: $root.templateFor($data), data: $data }"></div>
|
||||
<!-- /ko -->
|
||||
<!-- ko slimScrolledForeach: filesOnlyList -->
|
||||
<div class="entry" data-bind="attr: { id: $root.getEntryId($data) }, template: { name: $root.templateFor($data), data: $data }"></div>
|
||||
<!-- /ko -->
|
||||
<!-- ko slimScrolledForeach: foldersOnlyList -->
|
||||
<div class="entry" data-bind="attr: { id: $root.getEntryId($data) }, template: { name: $root.templateFor($data), data: $data }"></div>
|
||||
<!-- /ko -->
|
||||
<!-- ko slimScrolledForeach: filesOnlyList -->
|
||||
<div class="entry" data-bind="attr: { id: $root.getEntryId($data) }, template: { name: $root.templateFor($data), data: $data }"></div>
|
||||
<!-- /ko -->
|
||||
<!-- /ko -->
|
||||
|
||||
<!-- ko if: listStyle() == 'files_folders' -->
|
||||
<!-- ko slimScrolledForeach: filesOnlyList -->
|
||||
<div class="entry" data-bind="attr: { id: $root.getEntryId($data) }, template: { name: $root.templateFor($data), data: $data }"></div>
|
||||
<!-- /ko -->
|
||||
<!-- ko slimScrolledForeach: foldersOnlyList -->
|
||||
<div class="entry" data-bind="attr: { id: $root.getEntryId($data) }, template: { name: $root.templateFor($data), data: $data }"></div>
|
||||
<!-- /ko -->
|
||||
<!-- ko slimScrolledForeach: filesOnlyList -->
|
||||
<div class="entry" data-bind="attr: { id: $root.getEntryId($data) }, template: { name: $root.templateFor($data), data: $data }"></div>
|
||||
<!-- /ko -->
|
||||
<!-- ko slimScrolledForeach: foldersOnlyList -->
|
||||
<div class="entry" data-bind="attr: { id: $root.getEntryId($data) }, template: { name: $root.templateFor($data), data: $data }"></div>
|
||||
<!-- /ko -->
|
||||
<!-- /ko -->
|
||||
|
||||
<!-- ko if: listStyle() == 'mixed' -->
|
||||
<!-- ko slimScrolledForeach: listHelper.paginatedItems -->
|
||||
<div class="entry" data-bind="attr: { id: $root.getEntryId($data) }, template: { name: $root.templateFor($data), data: $data }"></div>
|
||||
<!-- /ko -->
|
||||
<!-- ko slimScrolledForeach: listHelper.paginatedItems -->
|
||||
<div class="entry" data-bind="attr: { id: $root.getEntryId($data) }, template: { name: $root.templateFor($data), data: $data }"></div>
|
||||
<!-- /ko -->
|
||||
<!-- /ko -->
|
||||
|
||||
<script type="text/html" id="files_template_machinecode">
|
||||
|
|
@ -54,8 +56,10 @@
|
|||
</script>
|
||||
|
||||
<script type="text/html" id="files_template_folder">
|
||||
<div class="title" data-bind="click: $root.changeFolder"><i class="icon-folder-open"></i> <span data-bind="text: name"></span></div>
|
||||
<div class="size">{{ _('Size') }}: <span data-bind="text: formatSize(size)"></span></div>
|
||||
<div data-bind="click: $root.changeFolder">
|
||||
<div class="title"><i class="icon-folder-open"></i> <span data-bind="text: name"></span></div>
|
||||
<div class="size">{{ _('Size') }}: <span data-bind="text: formatSize(size)"></span></div>
|
||||
</div>
|
||||
</script>
|
||||
</div>
|
||||
<div class="text-right muted" data-bind="attr: {title: diskusageString}, css: {'text-error': diskusageCritical}, style: {'font-weight': diskusageCritical() || diskusageWarning() ? 'bold' : 'normal'}">
|
||||
|
|
|
|||
Loading…
Reference in a new issue