diff --git a/bridge-client/build.gradle.kts b/bridge-client/build.gradle.kts index 6aeccdb0f..137431d21 100644 --- a/bridge-client/build.gradle.kts +++ b/bridge-client/build.gradle.kts @@ -30,6 +30,7 @@ sqldelight { val iosFrameworkName = "BridgeClient" kotlin { + targetHierarchy.default() androidTarget { publishAllLibraryVariants() compilations.all { @@ -48,6 +49,14 @@ kotlin { } } + jvm() { + compilations.all { + kotlinOptions { + jvmTarget = "1.8" + } + } + } + val xcframework = XCFramework(iosFrameworkName) // ios() includes x86 sim & arm64 device @@ -140,6 +149,12 @@ kotlin { val iosSimulatorArm64Test by sourceSets.getting iosSimulatorArm64Main.dependsOn(iosMain) iosSimulatorArm64Test.dependsOn(iosTest) + + sourceSets["jvmMain"].dependencies { + implementation(libs.sqlDelight.jvm) + implementation(libs.ktor.client.android) + } + } } android { diff --git a/bridge-client/src/commonMain/kotlin/org/sagebionetworks/bridge/kmm/shared/apis/AbstractApi.kt b/bridge-client/src/commonMain/kotlin/org/sagebionetworks/bridge/kmm/shared/apis/AbstractApi.kt index f2e84ee9e..a8a1350d0 100644 --- a/bridge-client/src/commonMain/kotlin/org/sagebionetworks/bridge/kmm/shared/apis/AbstractApi.kt +++ b/bridge-client/src/commonMain/kotlin/org/sagebionetworks/bridge/kmm/shared/apis/AbstractApi.kt @@ -6,7 +6,7 @@ import io.ktor.client.request.* import io.ktor.client.statement.* import io.ktor.http.* -internal abstract class AbstractApi(protected val basePath: String, protected val httpClient: HttpClient) { +abstract class AbstractApi(val basePath: String, val httpClient: HttpClient) { companion object { const val BASE_PATH = "https://webservices.sagebridge.org" @@ -17,7 +17,7 @@ internal abstract class AbstractApi(protected val basePath: String, protected va return postDataResponse(model, path).body() } - internal suspend inline fun postDataResponse(model: T, path: String) : HttpResponse { + suspend inline fun postDataResponse(model: T, path: String) : HttpResponse { val builder = HttpRequestBuilder() builder.method = HttpMethod.Post @@ -51,7 +51,7 @@ internal abstract class AbstractApi(protected val basePath: String, protected va return getDataResponse(path, modifiedDateTimeString, queryParams).body() } - internal suspend fun getDataResponse( + suspend fun getDataResponse( path: String, modifiedDateTimeString: String? = null, queryParams: Map? = null, diff --git a/bridge-client/src/commonMain/kotlin/org/sagebionetworks/bridge/kmm/shared/apis/AssessmentsApi.kt b/bridge-client/src/commonMain/kotlin/org/sagebionetworks/bridge/kmm/shared/apis/AssessmentsApi.kt index 9109d79bd..bf63c7d80 100644 --- a/bridge-client/src/commonMain/kotlin/org/sagebionetworks/bridge/kmm/shared/apis/AssessmentsApi.kt +++ b/bridge-client/src/commonMain/kotlin/org/sagebionetworks/bridge/kmm/shared/apis/AssessmentsApi.kt @@ -5,10 +5,12 @@ package org.sagebionetworks.bridge.kmm.shared.apis import io.ktor.client.* +import org.sagebionetworks.bridge.kmm.shared.models.Assessment import org.sagebionetworks.bridge.kmm.shared.models.AssessmentConfig import org.sagebionetworks.bridge.kmm.shared.models.AssessmentInfo +import org.sagebionetworks.bridge.kmm.shared.models.AssessmentList -internal class AssessmentsApi(basePath: String = BASE_PATH, httpClient: HttpClient) : AbstractApi(basePath, httpClient) { +class AssessmentsApi(basePath: String = BASE_PATH, httpClient: HttpClient) : AbstractApi(basePath, httpClient) { /** * Get the JSON config for this assessment @@ -30,4 +32,45 @@ internal class AssessmentsApi(basePath: String = BASE_PATH, httpClient: HttpClie return getData(assessmentInfo.configPath) } + /** + * Get a specific assessment revision. + * A GUID uniquely identifies a specific assessment revision. + * @param guid A guid + * @return Assessment + */ + suspend fun getAssessmentByGUID(guid: String) : Assessment { + return getData("v1/assessments/$guid") + } + + /** + * Get assessments in the app context. + * This is a paged API that can be filtered by the categories and tags assigned to assessments. The most recent (highest) revision of each assessment is returned in the API. + * @param offsetBy next page start offset for pagination (optional, default to 0) + * @param pageSize maximum number of records in each returned page (optional, default to 50) + * @param tag One or more tags. Every resource that has at least one of the tags will be returned (resources do not need to match all tags). (optional) + * @param includeDeleted Should deleted items be returned in results? (optional, default to false) + * @return AssessmentListComposed + */ + suspend fun getAssessments(offsetBy: Int? = 0, pageSize: Int? = 100, tag:String? = null, includeDeleted: Boolean? = false) : AssessmentList { + val parameters = mutableMapOf() + with(parameters) { + offsetBy?.let { put("offsetBy", it.toString()) } + pageSize?.let { put("pageSize", it.toString()) } + tag?.let { put("tag", it) } + includeDeleted?.let { put("includeDeleted", it.toString()) } + } + return getData("v1/assessments", queryParams = parameters) + } + + /** + * Update an assessment revision. + * A GUID uniquely identifies a specific assessment revision. Only members of the organization that own this assessment can update it. This operation returns the updated assessment revision. + * @param guid A guid + * @param assessment Updated assessment + * @return Assessment + */ + suspend fun updateAssessment(guid: String, assessment: Assessment) : Assessment { + return postData(assessment, "v1/assessments/$guid" ) + } + } diff --git a/bridge-client/src/commonMain/kotlin/org/sagebionetworks/bridge/kmm/shared/models/Assessment.kt b/bridge-client/src/commonMain/kotlin/org/sagebionetworks/bridge/kmm/shared/models/Assessment.kt new file mode 100644 index 000000000..d29309aad --- /dev/null +++ b/bridge-client/src/commonMain/kotlin/org/sagebionetworks/bridge/kmm/shared/models/Assessment.kt @@ -0,0 +1,179 @@ +/** +* Bridge Server API +* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) +* +* OpenAPI spec version: 0.25.33 +* +* +* NOTE: This class is auto generated by the swagger code generator program. +* https://github.com/swagger-api/swagger-codegen.git +* Do not edit the class manually. +*/ +package org.sagebionetworks.bridge.kmm.shared.models + + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + + +/** + * The assessment object contains the general cataloguing information we have on an assessment, and includes both a set of links to documents that describe the assessment and its use, as well as a configuration object for client applications. An assessment can be defined in an app context, or it can be shared in our shared assessment libary. Assessments are globally visible to all study authors in an app context, but are owned by a specific organization, and only members of that organization can edit the assessment. When shared, the configuration for an assessment is immutable and there are no APIs to update it. + * @param identifier A human-readable identifier for an assessment, which can have one or more revisions. + * @param revision + * @param ownerId The ID of the organization that owns this assessment. Only members of that organization will be able to edit the assessment, either in an app context or in the shared assessment library. + * @param title A name for the assessment that is shown to study designers, but not to study participants if there are labels that can be shown instead. + * @param osName The name of the operating system (conventional names are \"Android,\" \"iPhone OS,\" and \"Both\"). + * @param phase One of an enumerated list of states an assessment can be in. + * @param guid Each assessment revision is assigned a unique GUID which can be used to retrieve it through the API. Assessments will also have a unique combination of an identifier and a revision, and can be retrieved as a set of revisions under a given identifier. + * @param labels A collection of labels for this assessment. Only one label can be included for each language, and if the user’s language cannot be selected, English will be selected as a default. If an English label does not exist, then the assessment title can be used instead. + * @param colorScheme + * @param summary + * @param originGuid If this assessment was copied from a shared assessment, this will be the GUID of the shared assessment revision that was used to make this copy. Certain aspects of the assessment (notably, the assessment's configuration) are guaranteed to be identical to this origin assessment. + * @param validationStatus + * @param normingStatus + * @param minutesToComplete The number of minutes it takes for a participant to complete this assessment. + * @param tags A set of tags that apply to this assessment. Tags should be namespaced with a prefix followed by a period (e.g. \"category.neurodegenerative\"), as the tag API will give you these tags in a map keyed from the prefix to a list of the values under that prefix. + * @param customizationFields A map of AssessmentNode GUIDs to a set of field identifiers in that node that can be customized by developers without invalidating an assessment (the assessment will maintain its link to the shared assessment it was derived from, if any, and the authors of the assessment are confident that these changes to the configuration will not invalidate the scientific validity of the assessment). This specification guides validation of submissions to update an AssessmentNode through a specific customization API. + * @param createdOn The date and time the assessment was created. + * @param modifiedOn The date and time the assessment was last modified. + * @param deleted Has this assessment been logically deleted (an admin can restore it)? + * @param version The optimistic locking version of the assessment. This value must be submitted as part of the next update of the model. If it does not match the value on the server, a 409 error (Conflict) will prevent the update from occurring. It can also serve as a key to determine if a local cache of `Assessment` needs to be updated. + * @param imageResource + * @param frameworkIdentifier The framework this assessment belongs to. + * @param jsonSchemaUrl A URL for a resource specifying a JSON schema for the archived results. + * @param category The category of assessment. + * @param minAge The minimum age for which this assessment has been validated. + * @param maxAge The maximum age for which this assessment has been validated. + * @param additionalMetadata Additional metadata fields, expressed as a key-value map. + * @param type Assessment + */ +@Serializable +data class Assessment ( + /* A human-readable identifier for an assessment, which can have one or more revisions. */ + @SerialName("identifier") + val identifier: kotlin.String, + + @SerialName("revision") + val revision: kotlin.Long, + + /* The ID of the organization that owns this assessment. Only members of that organization will be able to edit the assessment, either in an app context or in the shared assessment library. */ + @SerialName("ownerId") + val ownerId: kotlin.String, + + /* A name for the assessment that is shown to study designers, but not to study participants if there are labels that can be shown instead. */ + @SerialName("title") + val title: kotlin.String, + + /* The name of the operating system (conventional names are \"Android,\" \"iPhone OS,\" and \"Both\"). */ + @SerialName("osName") + val osName: kotlin.String, + + /* One of an enumerated list of states an assessment can be in. */ + @SerialName("phase") + val phase: Assessment.Phase, + + /* Each assessment revision is assigned a unique GUID which can be used to retrieve it through the API. Assessments will also have a unique combination of an identifier and a revision, and can be retrieved as a set of revisions under a given identifier. */ + @SerialName("guid") + val guid: kotlin.String? = null, + + /* A collection of labels for this assessment. Only one label can be included for each language, and if the user’s language cannot be selected, English will be selected as a default. If an English label does not exist, then the assessment title can be used instead. */ + @SerialName("labels") + val labels: kotlin.collections.List