From 5df9b594223c0fca93349697dfc234c4c0c6f6a2 Mon Sep 17 00:00:00 2001 From: mkslofstra Date: Thu, 31 Oct 2024 09:31:17 +0100 Subject: [PATCH 1/2] chore: bump spotless version in gradle --- armadillo/build.gradle | 2 +- r/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/armadillo/build.gradle b/armadillo/build.gradle index 62e6cdaf7..a465d6ad0 100644 --- a/armadillo/build.gradle +++ b/armadillo/build.gradle @@ -98,7 +98,7 @@ jacocoTestReport { spotless { java { - googleJavaFormat('1.15.0') + googleJavaFormat('1.17.0') } } diff --git a/r/build.gradle b/r/build.gradle index 15a5e9154..2f2d54e8b 100644 --- a/r/build.gradle +++ b/r/build.gradle @@ -76,7 +76,7 @@ jacocoTestReport { spotless { java { - googleJavaFormat('1.15.0') + googleJavaFormat('1.17.0') } } From 19b296d14a5bd5b7f46c76b8e78ee23ff582bbb1 Mon Sep 17 00:00:00 2001 From: mkslofstra Date: Thu, 31 Oct 2024 09:41:14 +0100 Subject: [PATCH 2/2] chore: reformat files to match spotless again --- .../InvalidObjectNameException.java | 12 +-- .../armadillo/info/RProcessEndpoint.java | 6 +- .../armadillo/profile/ProfileScope.java | 1 + .../storage/ArmadilloStorageService.java | 19 ++-- .../armadillo/storage/ArmadilloWorkspace.java | 3 +- .../storage/ArmadilloLinkFileTest.java | 3 +- .../storage/ArmadilloStorageServiceTest.java | 14 +-- .../storage/ArmadilloWorkspaceTest.java | 2 +- ui/src/App.vue | 29 ++++-- ui/src/api/api.ts | 8 +- ui/src/components/DataPreviewTable.vue | 2 +- ui/src/components/FormValidation.vue | 22 ++--- ui/src/components/ViewEditor.vue | 89 +++++++++++++------ ui/src/helpers/utils.ts | 11 ++- ui/src/types/types.d.ts | 1 - ui/src/views/ProjectsExplorer.vue | 64 ++++++------- 16 files changed, 173 insertions(+), 113 deletions(-) diff --git a/armadillo/src/main/java/org/molgenis/armadillo/exceptions/InvalidObjectNameException.java b/armadillo/src/main/java/org/molgenis/armadillo/exceptions/InvalidObjectNameException.java index 10a2114ee..bc839df63 100644 --- a/armadillo/src/main/java/org/molgenis/armadillo/exceptions/InvalidObjectNameException.java +++ b/armadillo/src/main/java/org/molgenis/armadillo/exceptions/InvalidObjectNameException.java @@ -8,10 +8,10 @@ @ResponseStatus(BAD_REQUEST) public class InvalidObjectNameException extends RuntimeException { - public InvalidObjectNameException(String objectName) { - super( - format( - "Object name '%s' is invalid. Object format should be in the following format: folder/file.", - objectName)); - } + public InvalidObjectNameException(String objectName) { + super( + format( + "Object name '%s' is invalid. Object format should be in the following format: folder/file.", + objectName)); + } } diff --git a/armadillo/src/main/java/org/molgenis/armadillo/info/RProcessEndpoint.java b/armadillo/src/main/java/org/molgenis/armadillo/info/RProcessEndpoint.java index 0f0a430fc..0bd534614 100644 --- a/armadillo/src/main/java/org/molgenis/armadillo/info/RProcessEndpoint.java +++ b/armadillo/src/main/java/org/molgenis/armadillo/info/RProcessEndpoint.java @@ -1,5 +1,7 @@ package org.molgenis.armadillo.info; +import static org.molgenis.armadillo.security.RunAs.runAsSystem; + import java.util.List; import java.util.function.Function; import java.util.stream.Collectors; @@ -15,8 +17,6 @@ import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; import org.springframework.stereotype.Component; -import static org.molgenis.armadillo.security.RunAs.runAsSystem; - @Component @Endpoint(id = "rserveProcesses") public class RProcessEndpoint { @@ -43,7 +43,7 @@ public List getRServeEnvironments() { T doWithConnection(String environmentName, Function action) { var environment = - runAsSystem(profileService::getAll).stream() + runAsSystem(profileService::getAll).stream() .filter(it -> environmentName.equals(it.getName())) .map(ProfileConfig::toEnvironmentConfigProps) .findFirst() diff --git a/armadillo/src/main/java/org/molgenis/armadillo/profile/ProfileScope.java b/armadillo/src/main/java/org/molgenis/armadillo/profile/ProfileScope.java index 800a5dba3..be082c98e 100644 --- a/armadillo/src/main/java/org/molgenis/armadillo/profile/ProfileScope.java +++ b/armadillo/src/main/java/org/molgenis/armadillo/profile/ProfileScope.java @@ -11,6 +11,7 @@ @Component public class ProfileScope implements Scope { private static final Logger LOGGER = LoggerFactory.getLogger(ProfileScope.class); + /** Contains all profile scoped beans for all profiles */ private final ConcurrentHashMap scopedBeans = new ConcurrentHashMap<>(); diff --git a/armadillo/src/main/java/org/molgenis/armadillo/storage/ArmadilloStorageService.java b/armadillo/src/main/java/org/molgenis/armadillo/storage/ArmadilloStorageService.java index 6c543107e..f84fcd7d8 100644 --- a/armadillo/src/main/java/org/molgenis/armadillo/storage/ArmadilloStorageService.java +++ b/armadillo/src/main/java/org/molgenis/armadillo/storage/ArmadilloStorageService.java @@ -104,10 +104,10 @@ public void createLinkedObject( } try { ArmadilloLinkFile armadilloLinkFile = - createLinkFileFromSource(sourceProject, sourceObject, variables, linkName, linkProject); + createLinkFileFromSource(sourceProject, sourceObject, variables, linkName, linkProject); InputStream is = armadilloLinkFile.toStream(); storageService.save( - is, SHARED_PREFIX + linkProject, armadilloLinkFile.getFileName(), APPLICATION_JSON); + is, SHARED_PREFIX + linkProject, armadilloLinkFile.getFileName(), APPLICATION_JSON); } catch (IllegalArgumentException e) { throw new InvalidObjectNameException(linkName); } @@ -230,14 +230,15 @@ private static Workspace toWorkspace(ObjectMetadata item) { private void trySaveWorkspace(ArmadilloWorkspace workspace, Principal principal, String id) { try { storageService.save( - workspace.createInputStream(), - getUserBucketName(principal), - getWorkspaceObjectName(id), - APPLICATION_OCTET_STREAM); + workspace.createInputStream(), + getUserBucketName(principal), + getWorkspaceObjectName(id), + APPLICATION_OCTET_STREAM); } catch (StorageException e) { throw new StorageException(e); } } + public void saveWorkspace(InputStream is, Principal principal, String id) { // Load root dir File drive = new File("/"); @@ -249,9 +250,9 @@ public void saveWorkspace(InputStream is, Principal principal, String id) { trySaveWorkspace(workspace, principal, id); } else { throw new StorageException( - format( - "Can't save workspace: workspace too big (%s), not enough space left on device. Try to make your workspace smaller and/or contact the administrator to increase diskspace.", - getHumanReadableByteCount(fileSize))); + format( + "Can't save workspace: workspace too big (%s), not enough space left on device. Try to make your workspace smaller and/or contact the administrator to increase diskspace.", + getHumanReadableByteCount(fileSize))); } } catch (StorageException e) { throw new StorageException(e.getMessage().replace("load", "save")); diff --git a/armadillo/src/main/java/org/molgenis/armadillo/storage/ArmadilloWorkspace.java b/armadillo/src/main/java/org/molgenis/armadillo/storage/ArmadilloWorkspace.java index c1280bf83..85d80d4ab 100644 --- a/armadillo/src/main/java/org/molgenis/armadillo/storage/ArmadilloWorkspace.java +++ b/armadillo/src/main/java/org/molgenis/armadillo/storage/ArmadilloWorkspace.java @@ -7,7 +7,8 @@ public class ArmadilloWorkspace { byte[] content; - public static final String WORKSPACE_TOO_BIG_ERROR = "Unable to load workspace. Maximum supported workspace size is 2GB"; + public static final String WORKSPACE_TOO_BIG_ERROR = + "Unable to load workspace. Maximum supported workspace size is 2GB"; public ArmadilloWorkspace(InputStream is) { content = toByteArray(is); diff --git a/armadillo/src/test/java/org/molgenis/armadillo/storage/ArmadilloLinkFileTest.java b/armadillo/src/test/java/org/molgenis/armadillo/storage/ArmadilloLinkFileTest.java index b4887d1e0..6947c021a 100644 --- a/armadillo/src/test/java/org/molgenis/armadillo/storage/ArmadilloLinkFileTest.java +++ b/armadillo/src/test/java/org/molgenis/armadillo/storage/ArmadilloLinkFileTest.java @@ -21,7 +21,8 @@ public class ArmadilloLinkFileTest { String linkProject = "view-project"; ArmadilloLinkFile alf = new ArmadilloLinkFile(srcProject, srcObj, vars, linkObj, linkProject); - @Test void testThrowsIllegalArgumentExceptionWhenInvalidLinkObject() { + @Test + void testThrowsIllegalArgumentExceptionWhenInvalidLinkObject() { try { new ArmadilloLinkFile(srcProject, srcObj, vars, "broken", linkProject); } catch (IllegalArgumentException e) { diff --git a/armadillo/src/test/java/org/molgenis/armadillo/storage/ArmadilloStorageServiceTest.java b/armadillo/src/test/java/org/molgenis/armadillo/storage/ArmadilloStorageServiceTest.java index 4eca1b73f..4b5a057b5 100644 --- a/armadillo/src/test/java/org/molgenis/armadillo/storage/ArmadilloStorageServiceTest.java +++ b/armadillo/src/test/java/org/molgenis/armadillo/storage/ArmadilloStorageServiceTest.java @@ -520,11 +520,13 @@ void testSaveWorkspaceReturnsErrorWhenTooBig() { @Test void testSaveWorkspaceReturnsErrorWhenBiggerThan2Gbs() { - when(storageService.getWorkSpace(is)).thenThrow(new StorageException(ArmadilloWorkspace.WORKSPACE_TOO_BIG_ERROR)); + when(storageService.getWorkSpace(is)) + .thenThrow(new StorageException(ArmadilloWorkspace.WORKSPACE_TOO_BIG_ERROR)); try { armadilloStorage.saveWorkspace(is, principal, "test"); } catch (StorageException e) { - assertEquals("Unable to save workspace. Maximum supported workspace size is 2GB", e.getMessage()); + assertEquals( + "Unable to save workspace. Maximum supported workspace size is 2GB", e.getMessage()); } } @@ -617,10 +619,10 @@ void testCreateLinkedObjecInvalidLinkObj() { mockExistingObject(SHARED_GECKO, "1_0_release_1_1/gecko.parquet"); when(storageService.listBuckets()).thenReturn(List.of(SHARED_DIABETES, SHARED_GECKO)); assertThrows( - InvalidObjectNameException.class, - () -> - armadilloStorage.createLinkedObject( - "gecko", "1_0_release_1_1/gecko", "my_link", "diabetes", "a,b,c")); + InvalidObjectNameException.class, + () -> + armadilloStorage.createLinkedObject( + "gecko", "1_0_release_1_1/gecko", "my_link", "diabetes", "a,b,c")); } @Test diff --git a/armadillo/src/test/java/org/molgenis/armadillo/storage/ArmadilloWorkspaceTest.java b/armadillo/src/test/java/org/molgenis/armadillo/storage/ArmadilloWorkspaceTest.java index 8b6e22b85..83cb37b62 100644 --- a/armadillo/src/test/java/org/molgenis/armadillo/storage/ArmadilloWorkspaceTest.java +++ b/armadillo/src/test/java/org/molgenis/armadillo/storage/ArmadilloWorkspaceTest.java @@ -35,7 +35,7 @@ void testGetByteOfInputStreamThrowsMemoryError() throws IOException { when(isMock.read(any(byte[].class))).thenThrow(OutOfMemoryError.class); try { new ArmadilloWorkspace(isMock); - } catch(StorageException e) { + } catch (StorageException e) { assertEquals(ArmadilloWorkspace.WORKSPACE_TOO_BIG_ERROR, e.getMessage()); } } diff --git a/ui/src/App.vue b/ui/src/App.vue index f4f4e31a1..972860329 100644 --- a/ui/src/App.vue +++ b/ui/src/App.vue @@ -14,14 +14,20 @@ {{ diskSpaceMessage }} - You are logged in, but you don't have permission to access the Armadillo user interface. + You are logged in, but you don't have permission to access the + Armadillo user interface.
Don't worry, you can still do your research using the R client. - If you believe you should have permission to access this user interface, please contact an administrator. + If you believe you should have permission to access this user + interface, please contact an administrator.
{{ errorMessage }} - + @@ -36,10 +42,20 @@ import Tabs from "@/components/Tabs.vue"; import Login from "@/views/Login.vue"; import Alert from "@/components/Alert.vue"; import { defineComponent, onMounted, ref, Ref } from "vue"; -import { getPrincipal, getVersion, logout, getFreeDiskSpace, getPermissions } from "@/api/api"; +import { + getPrincipal, + getVersion, + logout, + getFreeDiskSpace, + getPermissions, +} from "@/api/api"; import { useRouter } from "vue-router"; import { ApiError } from "@/helpers/errors"; -import { diskSpaceBelowThreshold, convertBytes, isEmpty } from "@/helpers/utils"; +import { + diskSpaceBelowThreshold, + convertBytes, + isEmpty, +} from "@/helpers/utils"; export default defineComponent({ name: "ArmadilloPortal", @@ -77,8 +93,7 @@ export default defineComponent({ if (error.cause == 403) { isUnauthorised.value = true; } - }) - + }); }) .catch((error: ApiError) => { if (error.cause === 401) { diff --git a/ui/src/api/api.ts b/ui/src/api/api.ts index 47a6868e2..14f6207a0 100644 --- a/ui/src/api/api.ts +++ b/ui/src/api/api.ts @@ -17,7 +17,11 @@ import { Metrics, } from "@/types/api"; -import { ObjectWithStringKey, StringArray, ListOfObjectsWithStringKey } from "@/types/types"; +import { + ObjectWithStringKey, + StringArray, + ListOfObjectsWithStringKey, +} from "@/types/types"; import { APISettings } from "./config"; export async function get(url: string, auth: Auth | undefined = undefined) { @@ -199,7 +203,7 @@ export async function getProjects(): Promise { } export function getPermissions(): Promise { - return get("/access/permissions") + return get("/access/permissions"); } export async function getFiles(): Promise { diff --git a/ui/src/components/DataPreviewTable.vue b/ui/src/components/DataPreviewTable.vue index e820843b2..ff524ee9a 100644 --- a/ui/src/components/DataPreviewTable.vue +++ b/ui/src/components/DataPreviewTable.vue @@ -17,7 +17,7 @@ - {{ value.toString().slice(0, tableHeader[index].length - 2 ) }}.. + {{ value.toString().slice(0, tableHeader[index].length - 2) }}.. {{ value }} diff --git a/ui/src/components/FormValidation.vue b/ui/src/components/FormValidation.vue index b4e8daea9..33ec4da46 100644 --- a/ui/src/components/FormValidation.vue +++ b/ui/src/components/FormValidation.vue @@ -1,8 +1,11 @@ @@ -15,17 +18,17 @@ export default defineComponent({ props: { isValidated: { type: Boolean, - default: false + default: false, }, validationCondition: { type: Boolean, - required: true + required: true, }, invalidMessage: { type: String, - required: true - } - } + required: true, + }, + }, }); @@ -38,9 +41,8 @@ export default defineComponent({ } .feedback { - color: rgb(220, 53, 69); + color: rgb(220, 53, 69); font-style: italic; font-size: 0.9rem; } - - \ No newline at end of file + diff --git a/ui/src/components/ViewEditor.vue b/ui/src/components/ViewEditor.vue index 4070f35de..5ffb0cfce 100644 --- a/ui/src/components/ViewEditor.vue +++ b/ui/src/components/ViewEditor.vue @@ -16,10 +16,15 @@ disabled v-model="srcProject" /> - + @@ -36,7 +41,12 @@ disabled v-model="srcFolder" /> - + - +
+ class="p-3" + :isValidated="formValidated" + invalidMessage="Please select at least one variable" + :validationCondition="isEmpty(getSelectedVariables())" + > - +
- +
- + Save @@ -173,7 +207,7 @@ export default defineComponent({ components: { VariableSelector, Dropdown, - FormValidation + FormValidation, }, props: { sourceFolder: String, @@ -293,21 +327,24 @@ export default defineComponent({ this.srcTable = event.toString(); }, getSelectedVariables() { - return this.$refs.variableSelector && (this.$refs.variableSelector as any).selectedVariables ? (this.$refs.variableSelector as any).selectedVariables : []; + return this.$refs.variableSelector && + (this.$refs.variableSelector as any).selectedVariables + ? (this.$refs.variableSelector as any).selectedVariables + : []; }, saveIfValid(fileInfoSet: boolean, selectedVariables: StringArray) { - if(fileInfoSet && !isEmpty(selectedVariables)){ + if (fileInfoSet && !isEmpty(selectedVariables)) { this.onSave( - this.srcProject, - this.sourceObject, - this.vwProject, - this.linkedObject, - selectedVariables - ) + this.srcProject, + this.sourceObject, + this.vwProject, + this.linkedObject, + selectedVariables + ); } else { this.formValidated = true; } - } + }, }, watch: { srcProject() { @@ -329,8 +366,8 @@ export default defineComponent({ !isEmpty(this.vwProject) && !isEmpty(this.srcProject) && !isEmpty(this.srcFolder) && - !isEmpty(this.srcTable)); - + !isEmpty(this.srcTable) + ); }, linkedObject(): string { return `${this.vwFolder}/${this.vwTable}`; @@ -352,4 +389,4 @@ export default defineComponent({ }, }, }); - \ No newline at end of file + diff --git a/ui/src/helpers/utils.ts b/ui/src/helpers/utils.ts index 86a71e011..5b9405092 100644 --- a/ui/src/helpers/utils.ts +++ b/ui/src/helpers/utils.ts @@ -216,14 +216,19 @@ export function encodeUriComponent(component: string) { } export function diskSpaceBelowThreshold(diskSpace: number): boolean { - return !isEmpty(diskSpace)? diskSpace < 2147483648 : false; + return !isEmpty(diskSpace) ? diskSpace < 2147483648 : false; } export function isEmpty(variable: any): boolean { // function will return true if empty string, empty object or empty array, else false - if (variable === undefined || variable === null || variable === '' || Number.isNaN(variable)) { + if ( + variable === undefined || + variable === null || + variable === "" || + Number.isNaN(variable) + ) { return true; - } else if(typeof(variable) === 'object') { + } else if (typeof variable === "object") { if (Array.isArray(variable)) { return variable.length === 0; } else { diff --git a/ui/src/types/types.d.ts b/ui/src/types/types.d.ts index f2e8c9d2d..2ac2cee17 100644 --- a/ui/src/types/types.d.ts +++ b/ui/src/types/types.d.ts @@ -1,4 +1,3 @@ - import { Project, User } from "./api"; export type StringObject = Record>; diff --git a/ui/src/views/ProjectsExplorer.vue b/ui/src/views/ProjectsExplorer.vue index 496327735..764893b87 100644 --- a/ui/src/views/ProjectsExplorer.vue +++ b/ui/src/views/ProjectsExplorer.vue @@ -193,7 +193,11 @@
@@ -327,10 +331,7 @@ export default defineComponent({ this.isLinkFileType(this.selectedFile) ) { this.loading_preview = true; - previewObject( - this.projectId, - `${this.selectedObject}` - ) + previewObject(this.projectId, `${this.selectedObject}`) .then((data) => { this.filePreview = data; this.loading_preview = false; @@ -358,33 +359,30 @@ export default defineComponent({ return Object.keys(this.projectContent) as StringArray; }, selectedObject(): String { - return `${this.selectedFolder}/${this.selectedFile}` - } + return `${this.selectedFolder}/${this.selectedFile}`; + }, }, methods: { isTableType, isLinkFileType, isNonTableType, setFileDetails() { - getFileDetails( - this.projectId, - `${this.selectedObject}` - ) - .then((data) => { - this.fileInfo.fileSize = data["size"]; - this.fileInfo.dataSizeRows = parseInt(data["rows"]); - this.fileInfo.dataSizeColumns = parseInt(data["columns"]); - this.fileInfo.sourceLink = data["sourceLink"]; - this.fileInfo.variables = data["variables"]; - if (isLinkFileType(this.selectedFile)) { - this.columnNames = this.fileInfo.variables - } else { - this.setTableColumnNames( this.projectId, `${this.selectedObject}`) - } - }) - .catch((error) => { - this.errorMessage = `Cannot load details for [${this.selectedObject}] of project [${this.projectId}]. Because: ${error}.`; - }); + getFileDetails(this.projectId, `${this.selectedObject}`) + .then((data) => { + this.fileInfo.fileSize = data["size"]; + this.fileInfo.dataSizeRows = parseInt(data["rows"]); + this.fileInfo.dataSizeColumns = parseInt(data["columns"]); + this.fileInfo.sourceLink = data["sourceLink"]; + this.fileInfo.variables = data["variables"]; + if (isLinkFileType(this.selectedFile)) { + this.columnNames = this.fileInfo.variables; + } else { + this.setTableColumnNames(this.projectId, `${this.selectedObject}`); + } + }) + .catch((error) => { + this.errorMessage = `Cannot load details for [${this.selectedObject}] of project [${this.projectId}]. Because: ${error}.`; + }); }, askIfPreviewIsEmpty() { return isEmptyObject(this.filePreview[0]); @@ -424,13 +422,10 @@ export default defineComponent({ this.errorMessage = "Folder name cannot be empty"; } }, - setTableColumnNames (project: string, object: string) { - getTableVariables( - project, - object - ) + setTableColumnNames(project: string, object: string) { + getTableVariables(project, object) .then((data) => { - this.columnNames = data; + this.columnNames = data; }) .catch((error) => { this.errorMessage = `Cannot load column names for [${object}] of project [${project}]. Because: ${error}.`; @@ -465,10 +460,7 @@ export default defineComponent({ const splittedFileAndFolder = fileAndFolder.split("/"); const file = splittedFileAndFolder[1]; const folder = splittedFileAndFolder[0]; - const response = deleteObject( - this.projectId, - `${this.selectedObject}` - ); + const response = deleteObject(this.projectId, `${this.selectedObject}`); response .then(() => { this.selectedFile = "";