diff --git a/Project.toml b/Project.toml index 94b83e6..b5cd346 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "REDCap" uuid = "ba918724-fbf9-5e4a-a61c-87e95654e718" authors = ["Cory Cothrum", "Dilum Aluthge ", "Ashlin Harris "] -version = "2.4.0" +version = "2.5.0" [deps] Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" diff --git a/README.md b/README.md index c783fe8..5daa9d2 100644 --- a/README.md +++ b/README.md @@ -6,112 +6,23 @@ REDCap.jl is an API wrapper for REDCap v14, written in Julia. ## Examples ```julia -using REDCap +pkg> activate --temp; add REDCap +julia> using REDCap -export_version() +julia> export_version() -project_token = create_project( +julia> project_token = create_project( data = (project_title = "Test Project", purpose = 0), odm = "Data_Dictionary.xml") -import_records(token=project_token, data="example.csv", format=:csv) +julia> import_records(token=project_token, data="example.csv", format=:csv) -delete_records(token=project_token, records=[2,3]) +julia> delete_records(token=project_token, records=[2,3]) -export_logging(token=project_token) +julia> export_logging(token=project_token) ``` -## Syntax -Each REDCap method accepts a number of parameters that follow a shared naming convention. -REDCap.jl is designed to closely follow the design and syntax patterns of REDCap. -Every REDCap API method is available as a function that supplies certain required parameters and checks user inputs for validity. - -Return values and REDCap messages are returned as Strings directly, but the documentation shows how these can be parsed in useful ways. - -Function arguments are named after REDCap method parameters. -These are passed as named arguments and take values with intuitive types. - -### `token` and `url` -Nearly all REDCap methods accept a token that is unique to the project and user. - -The URL must exactly match this example: -```https://example.example/redcap/api/``` - -Your REDCap token and your institution's REDCap API URL can be read by default from Julia's environment variables. -You can make them avaiable to REDCap.jl by putting the following lines in [your local Julia startup file](https://docs.julialang.org/en/v1/manual/command-line-interface/#Startup-file) (probably `~/.julia/config/startup.jl`): -```julia -ENV["REDCAP_API_TOKEN"] = "C0FFEEC0AC0AC0DEC0FFEEC0AC0AC0DE" -ENV["REDCAP_API_URL"] = "http://example.com/redcap/api/" -``` -They can also be passed as ordinary named arguments. - -A few methods accept a super token, including `create_project`, which can be used to generate a project and project-level token. -If you have a super token, you might wish to keep that in your startup file, generating and saving project-level tokens as needed. - -### `data` -The `data` parameter contains a list of attributes. -In REDCap.jl, this can be a NamedTuple (or any derived type), a file handle, or a String. -If you use a NamedTuple, it will be translated internally into whatever `format` you use (xml by default). -```julia -import_project_info( - data=( - project_title="New name", - project_notes="New notes" - ), - returnFormat=:csv, -) -``` -But please keep in mind that a NamedTuple with one value must contain a comma: -```julia -import_project_info( - data=( - project_title="New name", # this comma is required - ), - returnFormat=:csv, -) -``` -A `Dict` value is fine as well. -```julia -import_project_info(data=Dict(:project_title=>"New name"), returnFormat=:csv) -``` -String values are accepted. If the string is a file name, the contents of the file are sent; otherwise, the value is sent directly as part of the API request. -```julia -data_string = """ - [{"data_access_group_name":"CA Site","unique_group_name":"ca_site"}, - {"data_access_group_name":"FL Site","unique_group_name":"fl_site"}, - {"data_access_group_name":"New Site","unique_group_name":""}] -""" -out = open("data_file.json","w"); write(out, data_string); close(out) - -import_DAGs(token=t,data=data_string, format=:json) # string is passed to the API - -import_DAGs(token=t, data="data_file.json", format=:json) # string is pattern-matched as a filename - -``` -As for collections, only collections of scalar entries are currently supported. -So, a list of attributes and values is accepted, but a Dict containing multiple rows per column can only be read in from a file. - -In the REDCap API, the presence of a `data` parameter often changes the behavior of a method. -For instance, most import methods are implemented as an export method with an added data parameter. -In REDCap.jl, it would be considered a bug for `import_project_data` to ever act as `export_project_data`, so the data paramater is almost always required where it is present. - -### `format` and `returnFormat` -Supported options are `:csv`, `:json`, `:xml` (the default value), and sometimes `:odm`. -These values can be passed as Strings or Symbols. - -Generally, the `format` parameter designates user input and the `returnFormat` parameter applies to REDCap messages and return values. -However, this is not consistent within REDCap. -REDCap.jl functions are designed to not accept any parameters that have no effect on the result. - -### `content` and `action` -The `content` and `action` parameters are what define each REDCap method, for the most part. -In REDCap.jl, these are passed internally and don't need to be supplied by the user. -Instead, they're fixed for each function. - -## Troubleshooting -If a function call doesn't produce the expected results, try making debug messages visible for this package by running `ENV["JULIA_DEBUG"] = REDCap`. -The data parameter is converted to a formatted string, so you might try different format parameters (`:csv`, `:json`, or `:xml`). -Feel free to create an issue for any unexpected errors, or for feature requests. +For more details, see the internal documentation (`help?> REDCap`). ## Acknowledgments The contributors are grateful for the support of Mary McGrath, Paul Stey, Fernando Gelin, the Brown Data Science Institute, the Brown Center for Biomedical Informatics, and the Tufts CTSI Informatics team. diff --git a/src/API_Methods.jl b/src/API_Methods.jl new file mode 100644 index 0000000..c6d217f --- /dev/null +++ b/src/API_Methods.jl @@ -0,0 +1,17 @@ +include("api_methods/arms.jl") +include("api_methods/data_access_groups.jl") +include("api_methods/events.jl") +include("api_methods/field_names.jl") +include("api_methods/files.jl") +include("api_methods/file_repository.jl") +include("api_methods/instruments.jl") +include("api_methods/logging.jl") +include("api_methods/metadata.jl") +include("api_methods/projects.jl") +include("api_methods/records.jl") +include("api_methods/redcap.jl") +include("api_methods/repeating_instruments_and_events.jl") +include("api_methods/reports.jl") +include("api_methods/surveys.jl") +include("api_methods/users.jl") +include("api_methods/user_roles.jl") diff --git a/src/REDCap.jl b/src/REDCap.jl index ae0810e..c75fdf6 100644 --- a/src/REDCap.jl +++ b/src/REDCap.jl @@ -1,3 +1,107 @@ +#TODO: some import methods can be used to delete entries +# Should this behavior be migrated to delete_* functions? + +""" +REDCap API methods are defined as named Julia functions. +The `content` and `action` parameters are managed internally. + +Function docstrings indicate how to use the Julia functions. +Refer to the official documentation for detailed specifications on the corresponding REDCap methods. + +## Syntax +Each REDCap method accepts a number of parameters that follow a shared naming convention. +REDCap.jl is designed to closely follow the design and syntax patterns of REDCap. +Every REDCap API method is available as a function that supplies certain required parameters and checks user inputs for validity. + +Return values and REDCap messages are returned as Strings directly, but the documentation shows how these can be parsed in useful ways. + +Function arguments are named after REDCap method parameters. +These are passed as named arguments and take values with intuitive types. + +### `token` and `url` +Nearly all REDCap methods accept a token that is unique to the project and user. + +The URL must exactly match this example: +```https://example.example/redcap/api/``` + +Your REDCap token and your institution's REDCap API URL can be read by default from Julia's environment variables. +You can make them avaiable to REDCap.jl by putting the following lines in [your local Julia startup file](https://docs.julialang.org/en/v1/manual/command-line-interface/#Startup-file) (probably `~/.julia/config/startup.jl`): +```julia +ENV["REDCAP_API_TOKEN"] = "C0FFEEC0AC0AC0DEC0FFEEC0AC0AC0DE" +ENV["REDCAP_API_URL"] = "http://example.com/redcap/api/" +``` +They can also be passed as ordinary named arguments. + +A few methods accept a super token, including `create_project`, which can be used to generate a project and project-level token. +If you have a super token, you might wish to keep that in your startup file, generating and saving project-level tokens as needed. + +### `data` +The `data` parameter contains a list of attributes, which varies between REDCap methods. +For definitive attribute lists, see the official REDCap documentation. +In REDCap.jl, this can be a NamedTuple (or any derived type), a file handle, or a String. +If you use a NamedTuple, it will be translated internally into whatever `format` you use (xml by default). +```julia +import_project_info( + data=( + project_title="New name", + project_notes="New notes" + ), + returnFormat=:csv, +) +``` +But please keep in mind that a NamedTuple with one value must contain a comma: +```julia +import_project_info( + data=( + project_title="New name", # this comma is required + ), + returnFormat=:csv, +) +``` +A `Dict` value is fine as well. +```julia +import_project_info(data=Dict(:project_title=>"New name"), returnFormat=:csv) +``` +String values are accepted. If the string is a file name, the contents of the file are sent; otherwise, the value is sent directly as part of the API request. +```julia +data_string = \"\"\" + [{"data_access_group_name":"CA Site","unique_group_name":"ca_site"}, + {"data_access_group_name":"FL Site","unique_group_name":"fl_site"}, + {"data_access_group_name":"New Site","unique_group_name":""}] +\"\"\" +out = open("data_file.json","w"); write(out, data_string); close(out) + +import_DAGs(token=t,data=data_string, format=:json) # string is passed to the API + +import_DAGs(token=t, data="data_file.json", format=:json) # string is pattern-matched as a filename + +``` +As for collections, only collections of scalar entries are currently supported. +So, a list of attributes and values is accepted, but a Dict containing multiple rows per column can only be read in from a file. + +In the REDCap API, the presence of a `data` parameter often changes the behavior of a method. +For instance, most import methods are implemented as an export method with an added data parameter. +In REDCap.jl, it would be considered a bug for `import_project_data` to ever act as `export_project_data`, so the data paramater is almost always required where it is present. + +### `format` and `returnFormat` +Supported options are `:csv`, `:json`, `:xml` (the default value), and sometimes `:odm`. +These values can be passed as Strings or Symbols. + +For import methods, the `format` parameter designates user input and the `returnFormat` parameter applies to REDCap messages and return values. +Otherwise, there is generally only a single `format` parameter that applies to REDCap messages and return values. + +### `content` and `action` +The `content` and `action` parameters are what define each REDCap method, for the most part. +In REDCap.jl, these are passed internally and don't need to be supplied by the user. +Instead, they're fixed for each function. + +## Troubleshooting +- If a function call doesn't produce the expected results, try making debug messages visible for this package by running `ENV["JULIA_DEBUG"] = REDCap`. +- The `data` parameter is converted to a formatted string, so you might try different format parameters (`:csv`, `:json`, or `:xml`). +If you're uncertain about the format for an input data parameter, try setting up an example in the browser and exporting the data. +You may have to remove the values for certain generated columns before importing. +- Feel free to create an issue for any unexpected errors, or for feature requests. +""" module REDCap using Dates @@ -10,22 +114,6 @@ include("types.jl") include("export.jl") include("request.jl") include("utils.jl") -include("api_methods/arms.jl") -include("api_methods/data_access_groups.jl") -include("api_methods/events.jl") -include("api_methods/field_names.jl") -include("api_methods/files.jl") -include("api_methods/file_repository.jl") -include("api_methods/instruments.jl") -include("api_methods/logging.jl") -include("api_methods/metadata.jl") -include("api_methods/projects.jl") -include("api_methods/records.jl") -include("api_methods/redcap.jl") -include("api_methods/repeating_instruments_and_events.jl") -include("api_methods/reports.jl") -include("api_methods/surveys.jl") -include("api_methods/users.jl") -include("api_methods/user_roles.jl") +include("API_Methods.jl") end diff --git a/src/api_methods/arms.jl b/src/api_methods/arms.jl index e887a9f..84ae1ab 100644 --- a/src/api_methods/arms.jl +++ b/src/api_methods/arms.jl @@ -1,28 +1,66 @@ -#TODO: consider changing all functions to the following form: -#= -function delete_arms(;kwargs...) - REDCap.request(;kwargs...) -end -=# +""" + function delete_arms(; url=get_url(), token=get_token(), arms,) + +Delete study arms from a REDCap project + +# Notes +If no value is provided for `arms`, all study arms are returned. +Deleting a study arm deletes any included records and data. -function delete_arms(; url=get_url(), token=get_token(), arms=nothing,) +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `arms`: names of study arms (can be scalar or vector) + +""" +function delete_arms(; url=get_url(), token=get_token(), arms,) REDCap.request(; url=REDCap_url(url), kwargs = (;token=REDCap_token(token), content=:arm, action=:import, arms,), ) end -function export_arms(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, arms=nothing,) +""" + function export_arms(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, arms=nothing,) + +Export a REDCap project's study arms + +# Notes +If no value is provided for `arms`, all study arms are returned. + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) +- `arms`: names of study arms (can be scalar or vector) + +""" +function export_arms(; url=get_url(), token=get_token(), format=nothing, arms=nothing,) REDCap.request(; url=REDCap_url(url), - kwargs = (; token=REDCap_token(token), content=:arm, format=REDCap_format(format), arms, returnFormat=REDCap_format(returnFormat),), + kwargs = (; token=REDCap_token(token), content=:arm, format=REDCap_format(format), arms,), ) end -#All examples use JSON -#TODO: what is the proper format for multi-item XML? I can't find this anywhere... -# #TODO: is this ata paratamet required, given the action parameter? -function import_arms(; url=get_url(), token=get_token(), format=nothing, data=nothing, returnFormat=nothing, override=nothing,) +""" + function import_arms(; url=get_url(), token=get_token(), format=nothing, data, returnFormat=nothing, override=nothing,) + +Import new study arms to a REDCap project, or rename existing arms + +# Notes +Deleting a study arm deletes any included records and data. + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `arms`: names of study arms (can be scalar or vector) +- `override`: if true, all existing arms are erased; if false (default), existing arms can only be renamed +- `data`: May be a String, a file name, or a data type such as NamedTuple or Dict +- `format`: the format of the `data` input parameter: `:csv`, `:json`, or `:xml` (default). If `data` is a String or a file name, this value must indicate the correct format. If `data` is a NamedTuple, Dict, or similar type, this value will determine what format will be used internally to pass on the data. +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" +function import_arms(; url=get_url(), token=get_token(), format=nothing, data, returnFormat=nothing, override=nothing,) REDCap.request(; url=REDCap_url(url), data=REDCap_data(data,REDCap_format(format),xml_tag="arms"), diff --git a/src/api_methods/data_access_groups.jl b/src/api_methods/data_access_groups.jl index cd9805a..175622a 100644 --- a/src/api_methods/data_access_groups.jl +++ b/src/api_methods/data_access_groups.jl @@ -1,11 +1,32 @@ -function delete_DAGs(; url=get_url(), token=get_token(), dags=nothing) +""" + function delete_DAGs(; url=get_url(), token=get_token(), dags) + +Delete Data Access Groups (DAGs) from a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `dags`: group names (can be scalar or vector) + +""" +function delete_DAGs(; url=get_url(), token=get_token(), dags) REDCap.request(; url=REDCap_url(url), kwargs = (; token=REDCap_token(token), content=:dag, action=:delete, dags,), ) end -#TODO: only accepts format, not returnFormat +""" + function export_DAGs(; url=get_url(), token=get_token(), format=nothing,) + +Export Data Access Groups (DAGs) from a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" function export_DAGs(; url=get_url(), token=get_token(), format=nothing,) REDCap.request(; url=REDCap_url(url), @@ -13,6 +34,17 @@ function export_DAGs(; url=get_url(), token=get_token(), format=nothing,) ) end +""" + function export_user_DAG_assignment(; url=get_url(), token=get_token(), format=nothing,) + +Export users' assignments to Data Access Groups (DAGs) for a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" function export_user_DAG_assignment(; url=get_url(), token=get_token(), format=nothing,) REDCap.request(; url=REDCap_url(url), @@ -20,7 +52,19 @@ function export_user_DAG_assignment(; url=get_url(), token=get_token(), format=n ) end -#TODO: data require here? +""" + function import_DAGs(; url=get_url(), token=get_token(), data, format=nothing, returnFormat=nothing,) + +Export users' assignments to Data Access Groups (DAGs) for a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `data`: May be a String, a file name, or a data type such as NamedTuple or Dict +- `format`: the format of the `data` input parameter: `:csv`, `:json`, or `:xml` (default). If `data` is a String or a file name, this value must indicate the correct format. If `data` is a NamedTuple, Dict, or similar type, this value will determine what format will be used internally to pass on the data. +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" function import_DAGs(; url=get_url(), token=get_token(), data=nothing, format=nothing, returnFormat=nothing,) REDCap.request(; url=REDCap_url(url), @@ -29,8 +73,20 @@ function import_DAGs(; url=get_url(), token=get_token(), data=nothing, format=no ) end -#TODO: data require here? -function import_user_DAG_assignment(; url=get_url(), token=get_token(), data=nothing, format=nothing, returnFormat=nothing,) +""" + function import_user_DAG_assignment(; url=get_url(), token=get_token(), data, format=nothing, returnFormat=nothing,) + +Export users' assignments to Data Access Groups (DAGs) for a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `data`: May be a String, a file name, or a data type such as NamedTuple or Dict +- `format`: the format of the `data` input parameter: `:csv`, `:json`, or `:xml` (default). If `data` is a String or a file name, this value must indicate the correct format. If `data` is a NamedTuple, Dict, or similar type, this value will determine what format will be used internally to pass on the data. +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" +function import_user_DAG_assignment(; url=get_url(), token=get_token(), data, format=nothing, returnFormat=nothing,) REDCap.request(; url=REDCap_url(url), data=REDCap_data(data,REDCap_format(format),xml_tag="items"), @@ -38,7 +94,19 @@ function import_user_DAG_assignment(; url=get_url(), token=get_token(), data=not ) end -function switch_DAG(; data, url=get_url(), dag=nothing) + +""" + function import_user_DAG_assignment(; url=get_url(), token=get_token(), data, format=nothing, returnFormat=nothing,) + +Switch the REDCap API user's current Data Access Group (DAG) + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `dag`: unique group name for the intended DAG + +""" +function switch_DAG(; data, url=get_url(), dag) REDCap.request(; url=REDCap_url(url), kwargs = (; token=REDCap_token(token), content=:dag, action=:switch, dag,), diff --git a/src/api_methods/events.jl b/src/api_methods/events.jl index 6da0878..e157bd3 100644 --- a/src/api_methods/events.jl +++ b/src/api_methods/events.jl @@ -1,21 +1,55 @@ +""" + function delete_events(; url=get_url(), token=get_token(), events=nothing,) + +Delete Events from a longitudinal REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `events`: unique event names (can be scalar or vector) + +""" function delete_events(; url=get_url(), token=get_token(), events=nothing,) REDCap.request(; url=REDCap_url(url), - kwargs = (; token=REDCap_token(token), content=:event, action=:import, events,), + kwargs = (; token=REDCap_token(token), content=:event, action=:delete, events,), ) end -function export_events(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, arms=nothing,) +""" + function export_events(; url=get_url(), token=get_token(), format=nothing, arms=nothing,) + +Export Events from a longitudinal REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) +- `arms`: study arms from which to pull events (all are inclued by default) +""" +function export_events(; url=get_url(), token=get_token(), format=nothing, arms=nothing,) REDCap.request(; url=REDCap_url(url), kwargs = (; token=REDCap_token(token), format=REDCap_format(format), returnFormat=REDCap_format(returnFormat), content=:event, arms,), ) end -#TODO: data parameter required? -function import_events(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, data=nothing, override=nothing,) +""" + function import_events(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, data=nothing, override=nothing,) + +Import new Events to a longitudinal REDCap project, or update the attributes of existing Events +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `data`: May be a String, a file name, or a data type such as NamedTuple or Dict +- `override`: if true, all existing Events are erased; if false (default), existing Events can only be updated +- `format`: the format of the `data` input parameter: `:csv`, `:json`, or `:xml` (default). If `data` is a String or a file name, this value must indicate the correct format. If `data` is a NamedTuple, Dict, or similar type, this value will determine what format will be used internally to pass on the data. +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" +function import_events(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, data=nothing, override=nothing,) REDCap.request(; url=REDCap_url(url), data=REDCap_data(data,REDCap_format(format),xml_tag="events"), diff --git a/src/api_methods/field_names.jl b/src/api_methods/field_names.jl index 6410f5c..822f925 100644 --- a/src/api_methods/field_names.jl +++ b/src/api_methods/field_names.jl @@ -1,8 +1,18 @@ #TODO: retire this old function name? ##TODO: what about export_fields? +""" + function export_list_of_export_field_names(; url=get_url(), token=get_token(), format=nothing, field=nothing) + +Export Events from a longitudinal REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) +- `field`: field variable names (can be scalar or vector). By default, all fields are returned. + +""" function export_list_of_export_field_names(; url=get_url(), token=get_token(), format=nothing, field=nothing) -#TODO: field could be a single entry or an array -##TODO: returnFormat has no effect, which I think is generally the case for export functions REDCap.request(; url=REDCap_url(url), kwargs = (; token=REDCap_token(token), content=:exportFieldNames, format=REDCap_format(format), field, ), diff --git a/src/api_methods/file_repository.jl b/src/api_methods/file_repository.jl index 481da7b..94edbd8 100644 --- a/src/api_methods/file_repository.jl +++ b/src/api_methods/file_repository.jl @@ -1,18 +1,56 @@ -function create_folder(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, name=nothing, folder_id=nothing, dag_id=nothing, role_id=nothing,) +#TODO: for 3.0, simplify a lot of these names +##TODO: check if these should have format and returnFormat, and make docstrings consistent +""" + function delete_DAGs(; url=get_url(), token=get_token(), dags) + +Create a New Folder in the File Repository + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `name`: name of the new folder (150 characters maximum) +- `folder_id`: folder_id of the intended parent directory (default is top-level directory in File Repository) +- `dag_id`: optionally restrict folder access to a Data Access Group +- `role_id`: optionally restrict folder access to a User Role + +""" +function create_folder(; url=get_url(), token=get_token(), name, folder_id=nothing, dag_id=nothing, role_id=nothing, format=nothing, returnFormat=nothing, ) REDCap.request(; url=REDCap_url(url), kwargs = (; token=REDCap_token(token), content=:fileRepository, action=:createFolder, name, format=REDCap_format(format), folder_id, dag_id, role_id, returnFormat=REDCap_format(returnFormat),), ) end -function delete_file_from_file_repository(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, name=nothing, doc_id=nothing,) +""" + function delete_file_from_file_repository(; url=get_url(), token=get_token(), doc_id,) + +Delete a File from the File Repository + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `doc_id`: the file's doc_id + +""" +function delete_file_from_file_repository(; url=get_url(), token=get_token(), doc_id,) REDCap.request(; url=REDCap_url(url), kwargs = (; token=REDCap_token(token), content=:fileRepository, action=:delete, doc_id, returnFormat=REDCap_format(returnFormat),), ) end -function export_file_from_file_repository(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, name=nothing, doc_id=nothing, +""" + function export_file_from_file_repository(; url=get_url(), token=get_token(), doc_id=nothing, + +Export a File from the File Repository + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `doc_id`: the file's doc_id + +""" +function export_file_from_file_repository(; url=get_url(), token=get_token(), doc_id=nothing, ) REDCap.request(; url=REDCap_url(url), @@ -20,7 +58,18 @@ function export_file_from_file_repository(; url=get_url(), token=get_token(), fo ) end -function export_list_of_folders(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, name=nothing, folder_id=nothing,) +""" + function export_list_of_folders(; url=get_url(), token=get_token(), folder_id=nothing,) + +Export a list of files for all subfolders + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `folder_id`: folder_id of intended folder (default is the top-level directory of the File Repository) + +""" +function export_list_of_folders(; url=get_url(), token=get_token(), folder_id=nothing, format=nothing) REDCap.request(; url=REDCap_url(url), kwargs = (; token=REDCap_token(token), content=:fileRepository, action=:list, name, format=REDCap_format(format), folder_id, returnFormat=REDCap_format(returnFormat),), @@ -28,7 +77,22 @@ function export_list_of_folders(; url=get_url(), token=get_token(), format=nothi end export_folders = export_list_of_folders +#TODO: this name is just incorrect... +""" +function import_file_from_file_repository(; url=get_url(), token=get_token(), format=nothing, file, folder_id=nothing,) + +Export a list of files for all subfolders function import_file_from_file_repository(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, name=nothing, file=nothing, folder_id=nothing,) + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `file`: contents of the new file +- `folder_id`: folder_id of intended folder (default is the top-level directory of the File Repository) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" +function import_file_from_file_repository(; url=get_url(), token=get_token(), format=nothing, file, folder_id=nothing,) REDCap.request(; url=REDCap_url(url), kwargs = (; token=REDCap_token(token), content=:fileRepository, action=:import, file, folder_id, returnFormat=REDCap_format(returnFormat),), diff --git a/src/api_methods/instruments.jl b/src/api_methods/instruments.jl index ef1654f..f89a69a 100644 --- a/src/api_methods/instruments.jl +++ b/src/api_methods/instruments.jl @@ -1,25 +1,77 @@ -function export_instrument_event_mappings(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, arms=nothing,) +""" + function export_instrument_event_mappings(; url=get_url(), token=get_token(), format=nothing, arms=nothing,) + +Export mappings of data collection instruments onto designated Events for a longitudinal REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) +- `arms`: study arms from which to pull events (all are inclued by default) + +""" +function export_instrument_event_mappings(; url=get_url(), token=get_token(), format=nothing, arms=nothing,) REDCap.request(; url=REDCap_url(url), - kwargs = (; token=REDCap_token(token), content=:formEventMapping, format=REDCap_format(format), arms, returnFormat=REDCap_format(returnFormat),), + kwargs = (; token=REDCap_token(token), content=:formEventMapping, format=REDCap_format(format), arms,), ) end +""" + function export_instruments(; url=get_url(), token=get_token(), format=nothing,) + +Export Instruments (Data Entry Forms) + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" function export_instruments(; url=get_url(), token=get_token(), format=nothing,) - #TODO: mention in docs that certain permissions are needed for various commands REDCap.request(; url=REDCap_url(url), kwargs = (; token=REDCap_token(token), content=:instrument, format=REDCap_format(format),), ) end -function export_PDF(; url=get_url(), token=get_token(), returnFormat=nothing, record=nothing, event=nothing, instrument=nothing, repeat_instance=nothing, allRecords=nothing, compactDisplay=nothing,) +""" + function export_PDF(; url=get_url(), token=get_token(), format=nothing, record=nothing, event=nothing, instrument=nothing, repeat_instance=nothing, allRecords=nothing, compactDisplay=nothing,) + +Export PDF of Data Collection Instruments + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) +- `record: record ID (default is a PDF with no data) +- `event`: unique event name for a longitudinal project +- `instrument`: unique instrument name +- `repeat_instance`: repeat instance number for projects with repeating instruments/events +- `allRecords`: if passed with any value, all records are exported +- `compactDisplay`: if true, excludes empty fields and unselected options (default is false) + +""" +function export_PDF(; url=get_url(), token=get_token(), format=nothing, record=nothing, event=nothing, instrument=nothing, repeat_instance=nothing, allRecords=nothing, compactDisplay=nothing,) REDCap.request(; url=REDCap_url(url), - kwargs = (; token=REDCap_token(token), content=:pdf, record, event, instrument, repeat_instance, allRecords, compactDisplay, returnFormat=REDCap_format(returnFormat),), + kwargs = (; token=REDCap_token(token), content=:pdf, record, event, instrument, repeat_instance, allRecords, compactDisplay, format=REDCap_format(format),), ) end +""" + function import_instrument_event_mappings(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, data,) + +Import mappings of data collection instruments onto designated Events for a longitudinal REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `data`: May be a String, a file name, or a data type such as NamedTuple or Dict +- `format`: the format of the `data` input parameter: `:csv`, `:json`, or `:xml` (default). If `data` is a String or a file name, this value must indicate the correct format. If `data` is a NamedTuple, Dict, or similar type, this value will determine what format will be used internally to pass on the data. +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" function import_instrument_event_mappings(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, data,) #TODO: Here and throughout, enforce that this function cannot #behave like an export, since the API calls are similar diff --git a/src/api_methods/logging.jl b/src/api_methods/logging.jl index 4a299fb..3ba7151 100644 --- a/src/api_methods/logging.jl +++ b/src/api_methods/logging.jl @@ -1,8 +1,24 @@ -#TODO: why does the returnFormat parameter not work? #TODO: What permissible values for logtype? -function export_logging(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, logtype=nothing, user=nothing, record=nothing, dag=nothing, beginTime=nothing, endTime=nothing,) +""" + function export_logging(; url=get_url(), token=get_token(), format=nothing, logtype=nothing, user=nothing, record=nothing, dag=nothing, beginTime=nothing, endTime=nothing,) + +Export mappings of data collection instruments onto designated Events for a longitudinal REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) +- `logtype`: optionally limit output to an event type (export, manage, user, record, record_add, record_edit, record_delete, lock_record, page_view) +- `user`: optionally limit output to a specific user +- `record`: optionally limit output to a specific record +- `dag`: optionally limit output to a specific Data Access Group (DAG) +- `beginTime`: optionally limit output to events logged after a given datetime +- `endTime`: optionally limit output to events logged before a given datetime + +""" +function export_logging(; url=get_url(), token=get_token(), format=nothing, logtype=nothing, user=nothing, record=nothing, dag=nothing, beginTime=nothing, endTime=nothing,) REDCap.request(; url=REDCap_url(url), - kwargs = (; token=REDCap_token(token), content=:log, format=REDCap_format(format), returnFormat=REDCap_format(returnFormat), logtype, user, record, dag, beginTime=REDCap_datetime(beginTime), endTime=REDCap_datetime(endTime),), + kwargs = (; token=REDCap_token(token), content=:log, format=REDCap_format(format), logtype, user, record, dag, beginTime=REDCap_datetime(beginTime), endTime=REDCap_datetime(endTime),), ) end diff --git a/src/api_methods/metadata.jl b/src/api_methods/metadata.jl index b5cf646..f4a8594 100644 --- a/src/api_methods/metadata.jl +++ b/src/api_methods/metadata.jl @@ -1,13 +1,38 @@ -#TODO: For most export functions, returnFormat seems to have no effect -function export_metadata(; url=get_url(), token=get_token(), format=nothing, fields=nothing, forms=nothing, returnFormat=nothing,) +""" + function export_metadata(; url=get_url(), token=get_token(), format=nothing, fields=nothing, forms=nothing,) + +Export metadata (Data Dictionary) from a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) +- `fields`: field names (can be scalar or vector). By default, all fields are pulled. +- `fields`: unique form names for data collection instruments (can be scalar or vector). By default, all fields are pulled. + +""" +function export_metadata(; url=get_url(), token=get_token(), format=nothing, fields=nothing, forms=nothing,) REDCap.request( url=REDCap_url(url), - kwargs = (; token=REDCap_token(token), content=:metadata, format=REDCap_format(format), fields, forms, returnFormat=REDCap_format(returnFormat),), + kwargs = (; token=REDCap_token(token), content=:metadata, format=REDCap_format(format), fields, forms,), ) end #TODO: there is no guidance on what the metadata should look like... is itbasically like the odm parameter in create_project? +""" +function import_metadata(; data, url=get_url(), token=get_token(), format=nothing, returnFormat=nothing,) + +Import metadata (Data Dictionary) to a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `data`: May be a String, a file name, or a data type such as NamedTuple or Dict +- `format`: the format of the `data` input parameter: `:csv`, `:json`, or `:xml` (default). If `data` is a String or a file name, this value must indicate the correct format. If `data` is a NamedTuple, Dict, or similar type, this value will determine what format will be used internally to pass on the data. +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" function import_metadata(; data, url=get_url(), token=get_token(), format=nothing, returnFormat=nothing,) REDCap.request(; url=REDCap_url(url), diff --git a/src/api_methods/projects.jl b/src/api_methods/projects.jl index 138ca56..0d5ee24 100644 --- a/src/api_methods/projects.jl +++ b/src/api_methods/projects.jl @@ -1,3 +1,16 @@ +""" + function create_project(; data, url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, odm=nothing,) + +Create a new REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `data`: May be a String, a file name, or a data type such as NamedTuple or Dict. Availabel attributes are project_title, purpose, purpose_other, project_notes, is_longitudinal, surveys_enabled, and record_autonumbering_enabled. +- `format`: the format of the `data` input parameter: `:csv`, `:json`, or `:xml` (default). If `data` is a String or a file name, this value must indicate the correct format. If `data` is a NamedTuple, Dict, or similar type, this value will determine what format will be used internally to pass on the data. +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" function create_project(; data, url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, odm=nothing,) #TODO: it might make sense to check these, but no check is done for formatted strings and file contents #@assert keys(data) ⊆ Set(:project_title, :purpose, :purpose_other, :project_notes, :is_longitudinal, :surveys_enabled, :record_autonumbering_enabled) @@ -7,13 +20,20 @@ function create_project(; data, url=get_url(), token=get_token(), format=nothing odm, kwargs = (;content=:project, format=REDCap_format(format), returnFormat=REDCap_format(returnFormat), token=REDCap_super_token(token),) ) - #TODO: should format be inferred? - #create_project(data;token=token,url=url,format=format,returnFormat=returnFormat,odm) end -function export_project_info(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing,) - #TODO: is this needed? - if !isnothing(returnFormat); throw(ArgumentError("returnFormat is ignored, so use format instead (possibly this is an issue with REDCap's API")) end +""" + function export_project_info(; url=get_url(), token=get_token(), format=nothing,) + +Export basic attributes of a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" +function export_project_info(; url=get_url(), token=get_token(), format=nothing,) REDCap.request(; url=REDCap_url(url), kwargs = (; content=:project, token=REDCap_token(token), format=REDCap_format(format),), @@ -21,6 +41,25 @@ function export_project_info(; url=get_url(), token=get_token(), format=nothing, end #TODO: should this write to a file? +""" + function export_project_XML(; url=get_url(), token=get_token(), returnFormat=nothing, returnMetadataOnly=nothing, records=nothing, fields=nothing, events=nothing, exportSurveyFields=nothing, exportDataAccessGroups=nothing, filterLogic=nothing, exportFiles=nothing,) + +Export an entire REDCap project as an XML project file, which can be used to create a new project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) +- `records`: optionally limit output to these record names (can be scalar or vector) +- `fields`: optionally limit output to these field names (can be scalar or vector) +- `events`: optionally limit output to these unique event names (can be scalar or vector) +- `returnMetadataOnly`: optionally return metadata with no data (default is false) +- `exportSurveyFields`: optionally export survey identifier and timestamp fields (default is false) +- `exportDataAccessGroups`: optionally export `redcap_data_access_group` field (default is false) +- `exportFiles`: optionally include contents of File Upload and Signature fields (default is false) +- `filterLogic`: logic string for filtering records + +""" function export_project_XML(; url=get_url(), token=get_token(), returnFormat=nothing, returnMetadataOnly=nothing, records=nothing, fields=nothing, events=nothing, exportSurveyFields=nothing, exportDataAccessGroups=nothing, filterLogic=nothing, exportFiles=nothing,) REDCap.request(; url=REDCap_url(url), @@ -28,16 +67,25 @@ function export_project_XML(; url=get_url(), token=get_token(), returnFormat=not ) end +""" + function import_project_info(; format=nothing, data, url=get_url(), token=get_token(),) + +Import basic attributes of a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `data`: May be a String, a file name, or a data type such as NamedTuple or Dict. Availabel attributes are project_title, project_language, purpose, purpose_other, project_notes, custom_record_label, secondary_unique_field, is_longitudinal, surveys_enabled, scheduling_enabled, record_autonumbering_enabled, randomization_enabled, project_irb_number, project_grant_number, project_pi_firstname, project_pi_lastname, display_today_now_button, iand bypass_branching_erase_field_prompt. +- `format`: the format of the `data` input parameter: `:csv`, `:json`, or `:xml` (default). If `data` is a String or a file name, this value must indicate the correct format. If `data` is a NamedTuple, Dict, or similar type, this value will determine what format will be used internally to pass on the data. + +""" function import_project_info(; format=nothing, data, url=get_url(), token=get_token(),) #TODO: not working, and there's no official API example... are we supposed to just pass this data in create_project? if REDCap_format(format) != REDCap_format(:csv); throw(ArgumentError("Only format=:csv is supported (possibly this is an issue with REDCap's API")) end - - #import_project_info(data; token=token, url=url, format=format) REDCap.request(; url=REDCap_url(url), data=REDCap_data(data,REDCap_format(format), xml_tag="items"), #TODO # without this xml tag, the XML is misformatted, but even with it, it isn't parse correctly... only csv works here.... - #project_title, project_language, purpose, purpose_other, project_notes, custom_record_label, secondary_unique_field, is_longitudinal, surveys_enabled, scheduling_enabled, record_autonumbering_enabled, randomization_enabled, project_irb_number, project_grant_number, project_pi_firstname, project_pi_lastname, display_today_now_button, bypass_branching_erase_field_prompt kwargs = (; token=REDCap_token(token), content=:project_settings, format=REDCap_format(format),), ) end diff --git a/src/api_methods/records.jl b/src/api_methods/records.jl index c3c1fe7..9afad91 100644 --- a/src/api_methods/records.jl +++ b/src/api_methods/records.jl @@ -1,4 +1,22 @@ +#TODO: add functino to delete all records + #TODO: is records required +""" + function delete_records(; url=get_url(), token=get_token(), records, arm=nothing, instrument=nothing, event=nothing, repeat_instance=nothing,) + +Delete records from a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `records`: record names (can be scalar or vector) +- `arm`: optionlly limit deletions to this arm number +- `instrument`: optionlly limit deletions to this unique instrument name +- `event`: optionlly limit deletions to this unique event name (required for longitudinal projects, otherwise unavailable) +- `repeat_instance`: optionlly limit deletions to this repeating instrument or event +- `delete_logging`: if true, delete logging activity for deleted record (default is false) + +""" function delete_records(; url=get_url(), token=get_token(), records, arm=nothing, instrument=nothing, event=nothing, repeat_instance=nothing,) REDCap.request( url=REDCap_url(url), @@ -6,9 +24,38 @@ function delete_records(; url=get_url(), token=get_token(), records, arm=nothing ) end +#TODO: There's some sort of field that just holds text, or ther fields, or something like that +#TODO: if you try to pull it, there will be no error, but it wn't exist in the output #TODO: this format parameter allows odm, unlike most other format args # The REDCap_listlike turns an input like [:a, :b, :c] into "a, b, c" # TODO: what other parameters need this sort of treatment? +""" + function export_records(; url=get_url(), token=get_token(), format=nothing, type=nothing, records=nothing, fields=nothing, forms=nothing, events=nothing, rawOrLabel=nothing, rawOrLabelHeaders=nothing, exportCheckboxLabel=nothing, returnFormat=nothing, exportSurveyFields=nothing, exportDataAccessGroups=nothing, filterLogic=nothing, dateRangeBegin=nothing, dateRangeEnd=nothing, csvDelimiter=nothing, decimalCharacter=nothing, exportBlankForGrayFormStatus=nothing) + +Export records from a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, `:xml` (default), or `:odm` +- `type`: `:flat` (default) or `:eav` +- `records`: optionally limit exports to specific records (can be scalar or vector) +- `fields`: optionally limit exports to specific field names (can be scalar or vector) +- `forms`: optionally limit exports to specific form names (can be scalar or vector) +- `events`: (longitudinal projects only) optionally limit exports to specific unique event names (can be scalar or vector) +- `rawOrLabel`: `:raw` (default, export raw coded values) or `:label` (export labels) +- `rawOrLabelHeaders`: (for `:flat` type, `:csv` format only) raw or label CSV headers +- `exportCheckboxLabel`: toggle format of checkbox field values (false by default) +- `exportSurveyFields`: optionally export survey identifier and timestamp fields (false by default) +- `exportDataAccessGroups`: optionally export the "redcap_data_access_group" field (false by default) +- `filterLogic` : optionally filter records based on a logic string +- `dateRangeBegin`: optionally limit output to records created or modified after a given datetime +- `dateRangeEnd`: optionally limit output to records created or modified before a given datetime +- `csvDelimiter`: ',' (default), 'tab', ';', '|', or '^' +- `decimalCharacter`: enforce ',' or '.' format (empty by default) +- `exportBlankForGrayFormStatus`: optionally export blank values for instrument complete status fields with a gray status icon + +""" function export_records(; url=get_url(), token=get_token(), format=nothing, type=nothing, records=nothing, fields=nothing, forms=nothing, events=nothing, rawOrLabel=nothing, rawOrLabelHeaders=nothing, exportCheckboxLabel=nothing, returnFormat=nothing, exportSurveyFields=nothing, exportDataAccessGroups=nothing, filterLogic=nothing, dateRangeBegin=nothing, dateRangeEnd=nothing, csvDelimiter=nothing, decimalCharacter=nothing, exportBlankForGrayFormStatus=nothing) REDCap.request( url=REDCap_url(url), @@ -16,6 +63,16 @@ function export_records(; url=get_url(), token=get_token(), format=nothing, type ) end +""" + function generate_next_record_name(; url=get_url(), token=get_token(),) + +Generate the next record name + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) + +""" function generate_next_record_name(; url=get_url(), token=get_token(),) REDCap.request( url=REDCap_url(url), @@ -23,6 +80,27 @@ function generate_next_record_name(; url=get_url(), token=get_token(),) ) end +""" + function import_records(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, type=nothing, overwriteBehavior=nothing, forceAutoNumber=nothing, backgroundProcess=nothing, data, dateFormat=nothing, csvDelimiter=nothing, returnContent=nothing,) + +Import records to a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, `:xml` (default), or `:odm` +- `type`: `:flat` (default) or `:eav` +- `overwriteBehavior`: overwrite data with blank values (by default, these are ignored) +- `forceAutoNumber`: optionally determine record numbers automatically (these must be provided by default) +- `backgroundProcess`: set to true for large uploads +- `data`: May be a String, a file name, or a data type such as NamedTuple or Dict +- `format`: the format of the `data` input parameter: `:csv`, `:json`, or `:xml` (default). If `data` is a String or a file name, this value must indicate the correct format. If `data` is a NamedTuple, Dict, or similar type, this value will determine what format will be used internally to pass on the data. +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) +- `dateFormat`: `:MDY`, `:DMY`, or `:YMD` (default) +- `csvDelimiter`: ',' (default), 'tab', ';', '|', or '^' +- `returnContent`: sets the return value (`:count` (default, `:lds`, or `:auto_lds`) + +""" #TODO: this format parameter allows odm, unlike most other format args function import_records(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, type=nothing, overwriteBehavior=nothing, forceAutoNumber=nothing, backgroundProcess=nothing, data, dateFormat=nothing, csvDelimiter=nothing, returnContent=nothing,) REDCap.request( @@ -32,6 +110,19 @@ function import_records(; url=get_url(), token=get_token(), format=nothing, retu ) end +""" + function rename_record(; url=get_url(), token=get_token(), record, new_record_name, arm=nothing,) + +Rename a record + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `record`: current record name +- `new_record_name`: new record name +- `arm`: optionally limit renaming to this arm number + +""" function rename_record(; url=get_url(), token=get_token(), record, new_record_name, arm=nothing,) REDCap.request( url=REDCap_url(url), diff --git a/src/api_methods/redcap.jl b/src/api_methods/redcap.jl index 381064a..fc18a3a 100644 --- a/src/api_methods/redcap.jl +++ b/src/api_methods/redcap.jl @@ -1,3 +1,13 @@ +""" + function export_version(; url=get_url(), token=get_token(),) + +Export the REDCap version + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) + +""" function export_version(; url=get_url(), token=get_token(),) REDCap.request(; url=REDCap_url(url), diff --git a/src/api_methods/repeating_instruments_and_events.jl b/src/api_methods/repeating_instruments_and_events.jl index 4c72667..8bbf1b5 100644 --- a/src/api_methods/repeating_instruments_and_events.jl +++ b/src/api_methods/repeating_instruments_and_events.jl @@ -1,3 +1,14 @@ +""" + function export_repeating_instruments_and_events(; url=get_url(), token=get_token(), format=nothing,) + +Export a list of repeating instruments and events for a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" function export_repeating_instruments_and_events(; url=get_url(), token=get_token(), format=nothing,) REDCap.request( url=REDCap_url(url), @@ -5,6 +16,19 @@ function export_repeating_instruments_and_events(; url=get_url(), token=get_toke ) end +""" + function import_repeating_instruments_and_events(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, data,) + +Import a list of repeating instruments and events to a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `data`: May be a String, a file name, or a data type such as NamedTuple or Dict +- `format`: the format of the `data` input parameter: `:csv`, `:json`, or `:xml` (default). If `data` is a String or a file name, this value must indicate the correct format. If `data` is a NamedTuple, Dict, or similar type, this value will determine what format will be used internally to pass on the data. +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" function import_repeating_instruments_and_events(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, data,) REDCap.request( url=REDCap_url(url), diff --git a/src/api_methods/reports.jl b/src/api_methods/reports.jl index 49926f4..f7937d3 100644 --- a/src/api_methods/reports.jl +++ b/src/api_methods/reports.jl @@ -1,5 +1,22 @@ #TODO: this format can include odm -function export_reports(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, fields=nothing, report_id=nothing, rawOrLabel=nothing, rawOrLabelHeaders=nothing, exportCheckboxLabel=nothing, csvDelimiter=nothing, decimalCharacter=nothing,) +""" + function export_reports(; url=get_url(), token=get_token(), report_id, format=nothing, returnFormat=nothing, fields=nothing, rawOrLabel=nothing, rawOrLabelHeaders=nothing, exportCheckboxLabel=nothing, csvDelimiter=nothing, decimalCharacter=nothing,) + +Export a report's data set for a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `report_id`: the report ID number +- `format`: the desired output format: `:csv`, `:json`, `:xml` (default), or `:odm` +- `rawOrLabel`: `:raw` (default, export raw coded values) or `:label` (export labels) +- `rawOrLabelHeaders`: (for `:flat` type, `:csv` format only) raw or label CSV headers +- `exportCheckboxLabel`: toggle format of checkbox field values (false by default) +- `csvDelimiter`: ',' (default), 'tab', ';', '|', or '^' +- `decimalCharacter`: enforce ',' or '.' format (empty by default) + +""" +function export_reports(; url=get_url(), token=get_token(), report_id, format=nothing, returnFormat=nothing, fields=nothing, rawOrLabel=nothing, rawOrLabelHeaders=nothing, exportCheckboxLabel=nothing, csvDelimiter=nothing, decimalCharacter=nothing,) REDCap.request( url=REDCap_url(url), kwargs = (; token=REDCap_token(token), content=:report, report_id, format=REDCap_format(format), returnFormat=REDCap_format(returnFormat), rawOrLabel, rawOrLabelHeaders, exportCheckboxLabel, csvDelimiter, decimalCharacter,), diff --git a/src/api_methods/surveys.jl b/src/api_methods/surveys.jl index 0daa4d9..55a4d57 100644 --- a/src/api_methods/surveys.jl +++ b/src/api_methods/surveys.jl @@ -1,3 +1,18 @@ +""" + function export_survey_link(; url=get_url(), token=get_token(), returnFormat=nothing, record=nothing, instrument=nothing, event=nothing, repeat_instance=nothing,) + +Export a participant's survey link for a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) +- `record`: the record name +- `instrument`: the instrument's name (must be enabled as a survey) +- `event`: the unique event name (longitudinal projects only) +- `repeat_instance`: the repeat instance of the event or instrument (default is 1) + +""" function export_survey_link(; url=get_url(), token=get_token(), returnFormat=nothing, record=nothing, instrument=nothing, event=nothing, repeat_instance=nothing,) REDCap.request( url=REDCap_url(url), @@ -5,6 +20,19 @@ function export_survey_link(; url=get_url(), token=get_token(), returnFormat=not ) end +""" + function export_survey_participants(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, instrument=nothing, event=nothing, repeat_instance=nothing,) + +Export a list of survey participants + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) +- `instrument`: the instrument's name (must be enabled as a survey) +- `event`: the unique event name (longitudinal projects only) + +""" function export_survey_participants(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, instrument=nothing, event=nothing, repeat_instance=nothing,) REDCap.request( url=REDCap_url(url), @@ -12,13 +40,40 @@ function export_survey_participants(; url=get_url(), token=get_token(), format=n ) end -function export_survey_queue_link(;record=nothing,returnFormat=:xml) +""" + function export_survey_queue_link(;record=nothing,returnFormat=nothing) + +Export a participant's survey queue link + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) +- `record`: the record name + +""" +function export_survey_queue_link(;record=nothing,returnFormat=nothing) REDCap.request( url=REDCap_url(url), kwargs = (; token=REDCap_token(token), content=:surveyQueueLink, record, returnFormat=REDCap_format(returnFormat),), ) end +""" + function export_survey_link(; url=get_url(), token=get_token(), returnFormat=nothing, record=nothing, instrument=nothing, event=nothing, repeat_instance=nothing,) + +Export a participant's survey return code + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) +- `record`: the record name +- `instrument`: the instrument's name (must be enabled as a survey) +- `event`: the unique event name (longitudinal projects only) +- `repeat_instance`: the repeat instance of the event or instrument (default is 1) + +""" function export_survey_return_code(; url=get_url(), token=get_token(), returnFormat=nothing, record=nothing, instrument=nothing, event=nothing, repeat_instance=nothing,) REDCap.request( url=REDCap_url(url), diff --git a/src/api_methods/user_roles.jl b/src/api_methods/user_roles.jl index 54b305e..effc2c2 100644 --- a/src/api_methods/user_roles.jl +++ b/src/api_methods/user_roles.jl @@ -1,38 +1,100 @@ -function delete_user_roles(; url=get_url(), token=get_token(), users=nothing,) +#TODO: 3.0 consider removing user from user role in function names +##TODO: OTOH, that would be yet another "R" name +""" + function delete_user_roles(; url=get_url(), token=get_token(), roles,) + +Delete roles from a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `roles`: unique role names (can be scalar or vector) + +""" +function delete_user_roles(; url=get_url(), token=get_token(), roles,) REDCap.request( url=REDCap_url(url), kwargs = (; token=REDCap_token(token), content=:userRole, action=:delete, roles,), ) end -function export_user_roles(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing,) +""" + function export_user_role_assignments(; url=get_url(), token=get_token(), format=nothing, ) + +Export role assignments from a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" +function export_user_role_assignments(; url=get_url(), token=get_token(), format=nothing, ) REDCap.request( url=REDCap_url(url), - kwargs = (; token=REDCap_token(token), content=:userRole, format=REDCap_format(format), returnFormat=REDCap_format(returnFormat),), + kwargs = (; token=REDCap_token(token), content=:userRoleMapping, format=REDCap_format(format), ), ) end -function import_user_roles(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, data, - ) +""" + function export_user_roles(; url=get_url(), token=get_token(), format=nothing,) + +Export roles from a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" +function export_user_roles(; url=get_url(), token=get_token(), format=nothing,) REDCap.request( url=REDCap_url(url), - data=REDCap_data(data,REDCap_format(format),xml_tag="users"), - kwargs = (; token=REDCap_token(token), content=:userRole, format=REDCap_format(format), returnFormat=REDCap_format(returnFormat),), + kwargs = (; token=REDCap_token(token), content=:userRole, format=REDCap_format(format),), ) end +""" + function import_user_role_assignments(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, data,) + +Import role assignments to a REDCap project -function export_user_role_assignments(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing,) +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `data`: May be a String, a file name, or a data type such as NamedTuple or Dict. Available attributes are user_name, unique_role_name, and data_access_group. +- `format`: the format of the `data` input parameter: `:csv`, `:json`, or `:xml` (default). If `data` is a String or a file name, this value must indicate the correct format. If `data` is a NamedTuple, Dict, or similar type, this value will determine what format will be used internally to pass on the data. +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" +function import_user_role_assignments(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, data,) REDCap.request( url=REDCap_url(url), + data=REDCap_data(data,REDCap_format(format),xml_tag="items"), kwargs = (; token=REDCap_token(token), content=:userRoleMapping, format=REDCap_format(format), returnFormat=REDCap_format(returnFormat),), ) end -function import_user_role_assignments(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, data,) +#TODO: for both import functions (?), You have to clear the unique_role_name column to import the roles you've exported from another project +""" + function import_user_roles(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, data, + +Import roles to a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `data`: May be a String, a file name, or a data type such as NamedTuple or Dict. Available attributes are unique_role_name, role_label, design, alerts, user_rights, data_access_groups, reports, stats_and_charts, manage_survey_participants, calendar, data_import_tool, data_comparison_tool, logging, email_logging, file_repository, data_quality_create, data_quality_execute, api_export, api_import, api_modules, mobile_app, mobile_app_download_data, record_create, record_rename, record_delete, lock_records_customization, lock_records, lock_records_all_forms, forms, and forms_export. +- `format`: the format of the `data` input parameter: `:csv`, `:json`, or `:xml` (default). If `data` is a String or a file name, this value must indicate the correct format. If `data` is a NamedTuple, Dict, or similar type, this value will determine what format will be used internally to pass on the data. +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" +function import_user_roles(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, data, + ) REDCap.request( url=REDCap_url(url), - data=REDCap_data(data,REDCap_format(format),xml_tag="items"), - kwargs = (; token=REDCap_token(token), content=:userRoleMapping, format=REDCap_format(format), returnFormat=REDCap_format(returnFormat),), + data=REDCap_data(data,REDCap_format(format),xml_tag="users"), + kwargs = (; token=REDCap_token(token), content=:userRole, format=REDCap_format(format), returnFormat=REDCap_format(returnFormat),), ) end + diff --git a/src/api_methods/users.jl b/src/api_methods/users.jl index cf4eb79..5948059 100644 --- a/src/api_methods/users.jl +++ b/src/api_methods/users.jl @@ -1,17 +1,52 @@ -function delete_users(; url=get_url(), token=get_token(), users=nothing,) +""" + function delete_users(; url=get_url(), token=get_token(), users) + +Delete users from a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `users`: user names (can be scalar or vector) + +""" +function delete_users(; url=get_url(), token=get_token(), users) REDCap.request( url=REDCap_url(url), kwargs = (; token=REDCap_token(token), content=:user, action=:delete, users,), ) end -function export_users(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing,) +""" + function export_users(; url=get_url(), token=get_token(), format=nothing,) + +Export users and user privileges for a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `format`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" +function export_users(; url=get_url(), token=get_token(), format=nothing,) REDCap.request( url=REDCap_url(url), - kwargs = (; token=REDCap_token(token), content=:user, format=REDCap_format(format), returnFormat=REDCap_format(returnFormat),), + kwargs = (; token=REDCap_token(token), content=:user, format=REDCap_format(format), ), ) end +""" + function import_users(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, data,) + +Import users and user privileges to a REDCap project + +# Named arguments +- `url`: (read from `ENV["REDCAP_API_URL"]` by default) +- `token`: an API token specific to the REDCap project and username (read from `ENV["REDCAP_API_TOKEN"]` by default) +- `data`: May be a String, a file name, or a data type such as NamedTuple or Dict. Available attributes are username, expiration, data_access_group, design, alerts, user_rights, data_access_groups, data_export, reports, stats_and_charts, manage_survey_participants, calendar, data_import_tool, data_comparison_tool, logging, email_logging, file_repository, data_quality_create, data_quality_execute, api_export, api_import, api_modules, mobile_app, mobile_app_download_data, record_create, record_rename, record_delete, lock_records_customization, lock_records, lock_records_all_forms, forms, and forms_export. +- `format`: the format of the `data` input parameter: `:csv`, `:json`, or `:xml` (default). If `data` is a String or a file name, this value must indicate the correct format. If `data` is a NamedTuple, Dict, or similar type, this value will determine what format will be used internally to pass on the data. +- `returnFormat`: the desired output format: `:csv`, `:json`, or `:xml` (default) + +""" function import_users(; url=get_url(), token=get_token(), format=nothing, returnFormat=nothing, data,) REDCap.request( url=REDCap_url(url), diff --git a/src/request.jl b/src/request.jl index 2e83f99..c6e5b87 100644 --- a/src/request.jl +++ b/src/request.jl @@ -1,8 +1,7 @@ #TODO: add something to automatically break files into < 500kb chunks? #There's also a new batchProcess parameter -#TODO: could enforce types here -function request(; url::URI, data=nothing, odm=nothing, kwargs) +function request(; url, data=nothing, odm=nothing, kwargs) html_request_body = generate_request_body(; data, odm, kwargs) @@ -52,15 +51,19 @@ function generate_request_body(; data=nothing, odm=nothing, kwargs) end append_as_redcap_pair!(d::Dict, parameter::Symbol, value::Nothing) = nothing +#TODO: deprecate this method, since we can filter by parameter name function append_as_redcap_pair!(d::Dict, parameter::Symbol, value::Vector) for (i, item) in enumerate(value) - # I believe either method should work: - d[string(parameter)] = join(value, ',') - #d[string(parameter,'[',i-1,']')] = string(item) + d[string(parameter,'[',i-1,']')] = string(item) end end function append_as_redcap_pair!(d::Dict, parameter::Symbol, value) - d[string(parameter)] = string(value) + #TODO: add all parameter names that take vector values + if parameter ∈ Set([:arms, :dags, :events, :field, :fields, :forms, :records, :roles, :users]) + d[string(parameter,"[0]")] = string(value) + else + d[string(parameter)] = string(value) + end end function as_redcap_data(data) diff --git a/test/runtests.jl b/test/runtests.jl index c566d96..50fcf40 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,3 +1,4 @@ +#TODO: test handlind parameters with scalar and vector inputs using REDCap using JSON using Test