diff --git a/app/models/folder.py b/app/models/folder.py deleted file mode 100644 index 180c337c..00000000 --- a/app/models/folder.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (C) 2023-2024 Indoc Systems -# -# Contact Indoc Systems for any questions regarding the use of this source code. - -from enum import Enum - - -class FolderType(str, Enum): - """Available folder types.""" - - NAMEFOLDER = 'namefolder' - PROJECTFOLDER = 'projectfolder' - - def get_prefix(self) -> str: - """Get the prefix for the folder type.""" - - prefix = { - 'namefolder': '', - 'projectfolder': 'shared/', - } - - return prefix.get(self.value) diff --git a/app/models/item.py b/app/models/item.py new file mode 100644 index 00000000..a7a91029 --- /dev/null +++ b/app/models/item.py @@ -0,0 +1,38 @@ +# Copyright (C) 2023-2024 Indoc Systems +# +# Contact Indoc Systems for any questions regarding the use of this source code. + +from enum import Enum + + +class ItemType(str, Enum): + """The class to reflect the type of item in database.""" + + FILE = 'file' + Folder = 'folder' + NAMEFOLDER = 'name_folder' + SHAREDFOLDER = 'project_folder' + + @classmethod + def get_type_from_keyword(self, keyword: str): + """The function will return the type of the item based on the keyword. + + - name folder will have keyword 'namefolder' as input + - project folder will not have any keyword + """ + + alternative_mapping = { + 'projectfolder': self.SHAREDFOLDER, + } + + return alternative_mapping.get(keyword, self.NAMEFOLDER) + + def get_prefix_by_type(self) -> str: + """Get the prefix for the folder type.""" + + prefix = { + self.NAMEFOLDER: '', + self.SHAREDFOLDER: 'shared/', + } + + return prefix.get(self.value, '') diff --git a/app/services/file_manager/file_list.py b/app/services/file_manager/file_list.py index 39982cd9..2131903a 100644 --- a/app/services/file_manager/file_list.py +++ b/app/services/file_manager/file_list.py @@ -9,6 +9,7 @@ import app.services.logger_services.log_functions as logger from app.configs.app_config import AppConfig from app.configs.user_config import UserConfig +from app.models.item import ItemType from app.models.service_meta_class import MetaService from app.services.output_manager.error_handler import ECustomizedError from app.services.output_manager.error_handler import SrvErrorHandler @@ -59,10 +60,20 @@ def list_files(self, paths, zone, page, page_size): # then format the console output files, folders = '', '' for f in res: - if 'file' == f.get('type'): + item_type = ItemType(f.get('type')) + # if there is space within the nane add double quotation to aviod confusion + if ' ' in f.get('name'): + f['name'] = f'"{f.get("name")}"' + + if item_type == ItemType.FILE: files = files + f.get('name') + ' ...' - elif f.get('type') in ['folder', 'name_folder', 'project_folder']: + else: + # add [p] in front of the project folder + if item_type == ItemType.SHAREDFOLDER: + f['name'] = f'[p]{f.get("name")}' + folders = folders + f"\033[34m{f.get('name')}\033[0m ..." + f_string = folders + files return f_string diff --git a/app/services/file_manager/file_upload/file_upload.py b/app/services/file_manager/file_upload/file_upload.py index 4dda080b..952ec259 100644 --- a/app/services/file_manager/file_upload/file_upload.py +++ b/app/services/file_manager/file_upload/file_upload.py @@ -18,7 +18,7 @@ import app.services.logger_services.log_functions as logger import app.services.output_manager.message_handler as mhandler from app.configs.app_config import AppConfig -from app.models.folder import FolderType +from app.models.item import ItemType from app.services.file_manager.file_upload.models import FileObject from app.services.file_manager.file_upload.models import ItemStatus from app.services.file_manager.file_upload.models import UploadType @@ -44,7 +44,7 @@ def compress_folder_to_zip(path): def assemble_path( - f: str, target_folder: str, project_code: str, folder_type: FolderType, zone: str + f: str, target_folder: str, project_code: str, folder_type: ItemType, zone: str ) -> Tuple[str, Dict, bool, str]: ''' Summary: @@ -80,8 +80,8 @@ def assemble_path( current_folder_node = target_folder if os.path.isfile(f) else current_file_path create_folder_flag = False # add prefix to folder - current_folder_node = folder_type.get_prefix() + current_folder_node - target_folder = folder_type.get_prefix() + target_folder + current_folder_node = folder_type.get_prefix_by_type() + current_folder_node + target_folder = folder_type.get_prefix_by_type() + target_folder if len(current_file_path.split('/')) > 2: sub_path = target_folder.split('/') diff --git a/app/utils/aggregated.py b/app/utils/aggregated.py index 662db673..e338ae5f 100644 --- a/app/utils/aggregated.py +++ b/app/utils/aggregated.py @@ -17,7 +17,7 @@ from app.configs.app_config import AppConfig from app.configs.config import ConfigClass from app.configs.user_config import UserConfig -from app.models.folder import FolderType +from app.models.item import ItemType from app.services.output_manager.error_handler import ECustomizedError from app.services.output_manager.error_handler import SrvErrorHandler from app.services.user_authentication.decorator import require_valid_token @@ -166,7 +166,7 @@ def get_file_in_folder(path): return files_list -def identify_target_folder(project_path: str) -> Tuple[str, FolderType, str]: +def identify_target_folder(project_path: str) -> Tuple[str, ItemType, str]: ''' Summary: the function will validate if input folder path doesn't @@ -187,14 +187,13 @@ def identify_target_folder(project_path: str) -> Tuple[str, FolderType, str]: # check folder type if is project folder or name folder # there will be a extra string for project folder between project code and folder name if len(temp_paths) == 2: - folder_type = FolderType.NAMEFOLDER + folder_type = ItemType.NAMEFOLDER folder_name = temp_paths[1] elif len(temp_paths) >= 3: - if temp_paths[1] == FolderType.PROJECTFOLDER.value: - folder_type = FolderType.PROJECTFOLDER + folder_type = ItemType.get_type_from_keyword(temp_paths[1]) + if folder_type == ItemType.SHAREDFOLDER: folder_name = temp_paths[2] else: - folder_type = FolderType.NAMEFOLDER folder_name = os.path.join(temp_paths[1], temp_paths[2]) else: SrvErrorHandler.customized_handle(ECustomizedError.INVALID_NAMEFOLDER, True) diff --git a/pyproject.toml b/pyproject.toml index 07a4eeb4..0ad2804c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "app" -version = "2.10.0" +version = "2.10.1" description = "This service is designed to support pilot platform" authors = ["Indoc Systems"] diff --git a/tests/app/commands/test_file.py b/tests/app/commands/test_file.py index 3abe2cab..ab9e64bc 100644 --- a/tests/app/commands/test_file.py +++ b/tests/app/commands/test_file.py @@ -185,7 +185,9 @@ def test_file_list_with_pagination_with_name_project_folder(requests_mock, mocke 'result': [ {'type': 'folder', 'name': 'folder1'}, {'type': 'name_folder', 'name': 'name_folder1'}, - {'type': 'project_folder', 'name': 'project_folder1'}, + {'type': 'project_folder', 'name': 'project folder1'}, + {'type': 'folder', 'name': 'test folder2'}, + {'type': 'project_folder', 'name': 'project folder2'}, ], }, ) @@ -193,7 +195,8 @@ def test_file_list_with_pagination_with_name_project_folder(requests_mock, mocke questionary.select.return_value.ask.return_value = 'exit' result = cli_runner.invoke(file_list, ['testproject/admin', '-z', 'greenroom']) outputs = result.output.split('\n') - assert outputs[0] == 'folder1 name_folder1 project_folder1 ' + assert outputs[0] == 'folder1 name_folder1 [p]"project folder1" ' + assert outputs[1] == '"test folder2" [p]"project folder2" ' def test_empty_file_list_with_pagination(requests_mock, mocker, cli_runner): diff --git a/tests/app/services/file_manager/file_upload/test_file_upload.py b/tests/app/services/file_manager/file_upload/test_file_upload.py index b4a9ffb2..fb385057 100644 --- a/tests/app/services/file_manager/file_upload/test_file_upload.py +++ b/tests/app/services/file_manager/file_upload/test_file_upload.py @@ -3,7 +3,7 @@ # Contact Indoc Systems for any questions regarding the use of this source code. from app.configs.app_config import AppConfig -from app.models.folder import FolderType +from app.models.item import ItemType from app.services.file_manager.file_upload.file_upload import assemble_path from app.services.file_manager.file_upload.file_upload import resume_upload from app.services.file_manager.file_upload.file_upload import simple_upload @@ -34,7 +34,7 @@ def test_assemble_path_at_name_folder(mocker): ) current_file_path, parent_folder, create_folder_flag, _ = assemble_path( - local_file_path, target_folder, project_code, FolderType.NAMEFOLDER, zone + local_file_path, target_folder, project_code, ItemType.NAMEFOLDER, zone ) assert current_file_path == 'admin/file.txt' assert parent_folder.get('name') == 'admin' @@ -71,9 +71,8 @@ def test_assemble_path_at_exsting_folder(mocker): ] mocker.patch('app.services.file_manager.file_upload.file_upload.search_item', side_effect=node_list) - current_file_path, parent_folder, create_folder_flag, _ = assemble_path( - local_file_path, target_folder, project_code, FolderType.NAMEFOLDER, zone + local_file_path, target_folder, project_code, ItemType.NAMEFOLDER, zone ) assert current_file_path == 'admin/test_folder_exist/file.txt' assert parent_folder.get('name') == 'test_folder_exist' @@ -104,7 +103,7 @@ def test_assemble_path_at_non_existing_folder(mocker): mocker.patch('app.services.file_manager.file_upload.file_upload.click.confirm', return_value=None) current_file_path, parent_folder, create_folder_flag, _ = assemble_path( - local_file_path, target_folder, project_code, FolderType.NAMEFOLDER, zone + local_file_path, target_folder, project_code, ItemType.NAMEFOLDER, zone ) assert current_file_path == 'admin/test_folder_not_exist' assert parent_folder.get('name') == 'admin' @@ -132,7 +131,7 @@ def test_assemble_path_at_project_folder(mocker): ) current_file_path, parent_folder, create_folder_flag, target_folder = assemble_path( - local_file_path, target_folder, project_code, FolderType.PROJECTFOLDER, zone + local_file_path, target_folder, project_code, ItemType.SHAREDFOLDER, zone ) assert current_file_path == 'shared/project_folder/file.txt' assert parent_folder.get('name') == 'project_folder' diff --git a/tests/app/utils/test_aggregated.py b/tests/app/utils/test_aggregated.py index 88194ca2..91454cbb 100644 --- a/tests/app/utils/test_aggregated.py +++ b/tests/app/utils/test_aggregated.py @@ -5,7 +5,7 @@ import pytest from app.configs.app_config import AppConfig -from app.models.folder import FolderType +from app.models.item import ItemType from app.utils.aggregated import check_item_duplication from app.utils.aggregated import identify_target_folder from app.utils.aggregated import search_item @@ -136,10 +136,10 @@ def test_validate_folder_name(folder_name): @pytest.mark.parametrize( 'input_path,expected_result', [ - ('project_code/username', ('project_code', FolderType.NAMEFOLDER, 'username')), - ('project_code/username/folder1', ('project_code', FolderType.NAMEFOLDER, 'username/folder1')), - ('project_code/projectfolder/folder1', ('project_code', FolderType.PROJECTFOLDER, 'folder1')), - ('project_code/projectfolder/folder1/folder2', ('project_code', FolderType.PROJECTFOLDER, 'folder1/folder2')), + ('project_code/username', ('project_code', ItemType.NAMEFOLDER, 'username')), + ('project_code/username/folder1', ('project_code', ItemType.NAMEFOLDER, 'username/folder1')), + ('project_code/projectfolder/folder1', ('project_code', ItemType.SHAREDFOLDER, 'folder1')), + ('project_code/projectfolder/folder1/folder2', ('project_code', ItemType.SHAREDFOLDER, 'folder1/folder2')), ], ) def test_identify_target_folder_success_with_different_path(mocker, input_path, expected_result):