:tocdepth: 3 Tips for customizing CDCS ========================= `Originally written by: Joshua Taillon -- ODI` `Last updated: November 15, 2019` The front-end for `NexusLIMS` is powered by the Configurable Data Curation System -- CDCS_. CDCS is a project originating from the Materials Genome Initiative (MGI) that provides a fully customizable platform with which to collect, organize, query, and disseminate scientific data. The data is fed into the system as individual `records` that must conform with a `template` (expressed using XML Schema). The records can then be searched and displayed using a customized `XSLT` stylesheet (eXtensible Stylesheet Language Transformations). These stylesheets can incorporate any arbitrary HTML and javascript, giving great control over what content is ultimately displayed to the end user when he or she opens a record. .. _CDCS: https://www.nist.gov/itl/ssd/information-systems-group/configurable-data-curation-system-cdcs Overview ++++++++ On the technical side, CDCS is implemented in Python using the Django framework and MongoDB for record storage in a NoSQL database. In addition to the actual record display that can be customized via XSLT, the Django framework allows any part of the entire CDCS application to be customized by overriding or changing the default `templates` (see `here `_ for more documentation on Django templates). Through this mechanism, any part of the application can be modified as needed. .. _DjangoTemplates: https://docs.djangoproject.com/en/2.2/topics/templates/ The specific implementation of CDCS used for `NexusLIMS` is stored in a `forked version `_ of the `upstream` CDCS `repository `_ available on the internal NIST Gitlab. CDCS is comprised of many individual Django `apps` (or `modules` -- see `here `_ for a complete list), that each control a different part or function of the overall application. For example, the ``core_explore_keyword_app`` controls the display of the data "search by keyword" page. .. _CDCSModules: https://www.nist.gov/itl/ssd/information-systems-group/cdcs-system-modules .. _NexusLIMSCDCSRepo: https://gitlab.nist.gov/gitlab/nexuslims/nexuslims-cdcs .. _CDCSRepo: https://github.com/usnistgov/MDCS Installation ++++++++++++ General documentation for the installation of CDCS is available from the `documentation site `_ of CDCS itself. The easiest way to install however, is using the Docker method, supplied by the developers of CDCS. The files for this can be obtained by `contacting `_ the developers directly, or by going to the `NexusLIMS repository `_ that holds instructions for installing the `NexusLIMS`-customized version (follow the instructions in the ``README.md`` file contained in that repository). If you proceed with the files from the `NexusLIMS` repository, the resulting product will contain all the `NexusLIMS` changes, rather than the default look-and-feel written by the CDCS developers (and as a result, will look just like `NexusLIMS`). .. _CDCSdocs: https://www.nist.gov/itl/ssd/information-systems-group/configurable-data-curation-system-cdcs/cdcs-help-and-resources .. _CDCScontact: https://www.nist.gov/itl/ssd/information-systems-group/configurable-data-curation-system-cdcs/contact-cdcs .. _NexusLIMSdocker: https://gitlab.nist.gov/gitlab/nexuslims/nexuslims-cdcs-docker-setup/tree/master After setting up an installation of CDCS (assuming an `MDCS` install rather than a `registry` install), there will be a few directories within the top-level folder displayed by the web server that can contain customizations. If the installation was performed using the `docker method `_, then this top-level folder is the ``/srv/curator`` directory in the ``mdcs_cdcs_1`` container. This can be accessed by telling docker to execute an interactive ``bash`` shell within the container from your host system: .. code:: bash docker exec -it mdcs_cdcs_1 bash .. admonition:: A development tip... Microsoft's [1]_ freely-available `Visual Studio Code `_ supports connecting to existing Docker containers and editing the files inside that container on-the-fly. This makes rapid prototyping significantly easier, as you can edit files within the container using modern IDE tools and see the impact of certain changes in realtime. See the `documentation `_ of the container features in VS Code for more detail. `This `_ page also describes how to connect to a container that may be on an SSH-accessible remote host. .. _VSCode: https://code.visualstudio.com/ .. _VSCodeContainerDocs: https://code.visualstudio.com/docs/remote/containers .. _VSCodeContainerRemoteDocs: https://code.visualstudio.com/docs/remote/containers-advanced#_developing-inside-a-container-on-a-remote-docker-host Since CDCS is a Django application, the structure will be familiar to anyone that has done Django development previously. The ``templates`` folder contains the HTML-format Django templates that are used to construct the pages, the ``static`` folder contains various `static` resources (such as images, CSS files, javascript files, etc.) that can be accessed from anywhere on the site, and ``mdcs_home`` is the "homepage" app that is designed to allow easy customization of a few high-level CDCS elements. The following sections go into each of these in more detail. To view the specific changes that were made, the `NexusLIMS` CDCS `git commit history `_ will show every change in detail from what is provided in the default CDCS installation. .. _nexuslimsCDCSGitCommits: https://gitlab.nist.gov/gitlab/nexuslims/nexuslims-cdcs/commits/NexusLIMS_master General tips ++++++++++++ A couple general strategies help when trying to customize various pieces of the CDCS installation. It is common not to know where to look when trying to change a piece of text or the structure of a section, since the application is split into many different Django `apps` (Python modules) that are all included as part of the default installation. The only `app` immediately visible from the root directory of ``/srv/curator`` is the ``mdcs_home`` app. The others (at least in the docker-installed version -- listed `here `_) are located in the ``/usr/local/lib/python3.6/site-packages`` folder holding the libraries for the system-level Python installation. The easiest way to determine what needs to be changed is to use the `find in files` feature supplied by most modern code editors/IDEs. After making sure both the ``/srv/curator`` and ``site-packages`` directories are included in the search, enter the text (from the website) that you wish to change, and you should be able to narrow down what specific file is controlling that display. For non-text or other elements, you can use your web browser's `inspect` feature (usually found by right-clicking on a certain item) to find an element's HTML `id`, `name`, or `class`, which can be used as above to find the file providing that element. If the file you find is within the ``site-packages`` folder, you will need to `override `_ that template, rather than making changes directly to the file (see the templates_ section for more detail). Once you make any changes to the files inside ``/srv/curator``, you will need to reload Django in order to show any of those changes. This can be done by restarting the Docker container, or you can get Django to restart itself automatically by "touching" a special file in the ``mdcs`` directory: .. code:: bash # run from within the mdcs_cdcs_1 docker container: touch /srv/curator/mdcs/wsgi.py .. _DjangoOverridingTemplates: https://docs.djangoproject.com/en/2.2/howto/overriding-templates/#overriding-templates The ``static`` folder +++++++++++++++++++++ .. _static: The ``static`` folder contains resources that can be used on any page within the Django application, such as images, javascript, CSS style definitions, individual files to serve, etc. (see documentation about the concept of static files in Django `here `_). For quick customizations, a few files in particular are good to know about. ``./static/css/extra.css`` is sourced on every page within the application, and this is a good place to put any custom style definitions. Some example changes that we made to this file were modifying the spacing between items, changing item colors, etc. Changes can also be made to ``./static/css/main.css``, but keeping all modifications in one file will help make maintenance on these settings easier. Simply changing or placing files into the ``static`` directory will not immediately make them visible, since we have to instruct Django to "collect" these files. This is because Django serves the static files out of a different directory (at least in the Docker-installed version) named ``static.prod``. You can either manually copy any changed files into the ``static.prod`` directory (after logging into the docker container with ``docker exec -it mdcs_cdcs_1 bash``) with a command like: .. code:: bash cp -R /srv/curator/static/* /srv/curator/static.prod/ Or you can instruct Django to do this for you (the recommended method) using the |DjangoCollectStatic|_. From the ``/srv/curator`` directory inside the ``mdcs_cdcs_1`` container, run the following: .. |DjangoCollectStatic| replace:: ``collectstatic`` command .. _DjangoCollectStatic: https://docs.djangoproject.com/en/2.2/ref/contrib/staticfiles/ .. _DjangoStatic: https://docs.djangoproject.com/en/2.2/howto/static-files/ .. _collectStatic: .. code:: bash python manage.py collectstatic -c --noinput This may take a little bit of time depending on how many files you have, but the command will completely clear the ``static.prod`` folder, and copy all the files you placed in the ``static`` folder into the right place. To actually use the files that are in the ``static`` folder, you will need to use the ``static`` `template tag` (documented `here `_) within your templates. `Template tags` are specially-formatted bits of code that Django parses within the HTML templates that allow for dynamic content (see the next section). Template tags in Django are signified using curly braces and percent symbols ``{% ... %}`` followed by whichever tag you want to use. As an example, you would use the following syntax to include an image stored at ``/srv/curator/static/img/example.jpg`` from within a Django template: .. code:: django My image If you peruse around the included templates in the ``templates`` folder, you will see this syntax all over, for example in ``