diff --git a/PLAN b/PLAN deleted file mode 100644 index c45bdde92..000000000 --- a/PLAN +++ /dev/null @@ -1 +0,0 @@ -The datatracker development plan is no longer maintained in this file. Contact the tools-development team for details on the current plan. diff --git a/README-CDN.rst b/README-CDN.rst deleted file mode 100644 index f4f194289..000000000 --- a/README-CDN.rst +++ /dev/null @@ -1,183 +0,0 @@ -================================================================================ - Serving Static Datatracker Files via a CDN -================================================================================ - -Intro -===== - -With release 6.4.0, the way that the static files used by the datatracker are -handled changes substantially. Static files were previously versioned under a -top-level ``static/`` directory, but this is not the case any more. External -files (such as for instance ``jquery.min.js``) are now placed under -``ietf/externals/static/`` and updated using a tool called bower_, while -datatracker-specific files (images, css, js, etc.) are located under -``ietf/static/ietf/`` and ``ietf/secr/static/secr/`` respectively. - -The following sections provide more details about handling of internals, -externals, and how deployment is done. - - -Serving Static Files via CDN -============================ - -Production Mode ---------------- - -If resources served over a CDN and/or with a high max-age don't have different -URLs for different versions, then any component upgrade which is accompanied -by a change in template functionality will have a long transition time -during which the new pages are served with old components, with possible -breakage. We want to avoid this. - -The intention is that after a release has been checked out, but before it is -deployed, the standard django 'collectstatic' management command will be -run, resulting in all static files being collected from their working -directory location and placed in an appropiate location for serving via CDN. -This location will have the datatracker release version as part of its URL, -so that after the deployment of a new release, the CDN will be forced to fetch -the appropriate static files for that release. - -An important part of this is to set up the ``STATIC_ROOT`` and ``STATIC_URL`` -settings appropriately. In 6.4.0, the setting is as follows in production -mode:: - - STATIC_URL = "https://www.ietf.org/lib/dt/%s/"%__version__ - STATIC_ROOT = CDN_ROOT + "/a/www/www6s/lib/dt/%s/"%__version__ - -The result is that all static files collected via the ``collectstatic`` -command will be placed in a location served via CDN, with the release -version being part of the URL. - -Development Mode ----------------- - -In development mode, ``STATIC_URL`` is set to ``/static/``, and Django's -``staticfiles`` infrastructure makes the static files available under that -local URL root (unless you set -``settings.SERVE_CDN_FILES_LOCALLY_IN_DEV_MODE`` to ``False``). It is not -necessary to actually populate the ``static/`` directory by running -``collectstatic`` in order for static files to be served when running -``ietf/manage.py runserver`` -- the ``runserver`` command has extra support -for finding and serving static files without running collectstatic. - -In order to work backwards from a file served in development mode to the -location from which it is served, the mapping is as follows:: - - ============================== ============================== - Development URL Working copy location - ============================== ============================== - localhost:8000/static/ietf/* ietf/static/ietf/* - localhost:8000/static/secr/* ietf/secr/static/secr/* - localhost:8000/static/* ietf/externals/static/* - ============================== ============================== - -Handling of External Javascript and CSS Components -================================================== - -In order to make it easy to keep track of and upgrade external components, -these are now handled by a tool called ``bower``, via a new management -command ``bower_install``. Each external component is listed in a file -``ietf/bower.json``. In order to update the version of a component listed in -``ietf/bower.json``, or add a new one, you should edit ``bower.json``, and -then run the management command:: - - $ ietf/manage.py bower_install - -(Not surprisingly, you need to have bower_ installed in order to use this -management command.) - -That command will fetch the required version of each external component listed -in ``bower.json`` (actually, it will do this for *all* ``bower.json`` files -found in the ``static/`` directories of all ``INSTALLED_APPS`` and the -directories in ``settings.STATICFILES_DIRS``), saving them temporarily under -``.tmp/bower_components/``; it will then extract the relevant production -``js`` and ``css`` files and place them in an appropriately named directory -under ``ietf/externals/static/``. The latter location is taken from -``COMPONENT_ROOT`` in ``settings.py``. - -Managing external components via bower has the additional benefit of -managing dependencies -- components that have dependencies will pull in -these, so that they also are placed under ``ietf/externals/static/``. -You still have to manually add the necessary stylesheet and/or javascript -references to your templates, though. - -The ``bower_install`` command is not run automatically by ``bin/mkrelease``, -since it needs an updated ``bower.json`` in order to do anything interesting. -So when you're intending to update an external web asset to a newer version, -you need to edit the ``bower.json`` file, run ``manage.py bower_install``, -verify that the new version doesn't break things, and then commit the new -files under ``ietf/externals/static/`` and the updated ``bower.json``. - -.. _bower: http://bower.io/ - -The ``ietf/externals/static/`` Directory ------------------------------------------ - -The directory ``ietf/externals/static/`` holds a number of subdirectories -which hold distribution files for external client-side components, collected -by ``bower_install`` as described above. Currently -(01 Aug 2015) this means ``js`` and ``css`` components and fonts. - -These components each reside in their own subdirectory, which is named with -the component name:: - - henrik@zinfandel $ ls -l ietf/externals/static/ - total 40 - drwxr-xr-x 6 henrik henrik 4096 Jul 25 15:25 bootstrap - drwxr-xr-x 4 henrik henrik 4096 Jul 25 15:25 bootstrap-datepicker - drwxr-xr-x 4 henrik henrik 4096 Jul 25 15:25 font-awesome - drwxr-xr-x 2 henrik henrik 4096 Jul 25 15:25 jquery - drwxr-xr-x 2 henrik henrik 4096 Jul 25 15:25 jquery.cookie - drwxr-xr-x 2 henrik henrik 4096 Jul 25 15:24 ptmono - drwxr-xr-x 2 henrik henrik 4096 Jul 25 15:24 ptsans - drwxr-xr-x 2 henrik henrik 4096 Jul 25 15:24 ptserif - drwxr-xr-x 2 henrik henrik 4096 Jul 25 15:25 select2 - drwxr-xr-x 2 henrik henrik 4096 Jul 25 15:25 select2-bootstrap-css - -The ``pt*`` fonts are an exception, in that there is no bower component -available for these fonts, so they have been put in place manually. - - -Handling of Internal Static Files -================================= - -Previous to this release, internal static files were located under -``static/``, mixed together with the external components. They are now -located under ``ietf/static/ietf/`` and ``ietf/secr/static/secr``, and will be -collected for serving via CDN by the ``collectstatic`` command. Any static -files associated with a particular app will be handled the same way (which -means that all ``admin/`` static files automatically will be handled correctly, too). - -Handling of Customised Bootstrap Files -====================================== - -We are using a customised version of Bootstrap_, which is handled specially, -by a SVN externals definition in ``ietf/static/ietf``. That pulls the content -of the ``bootstrap/dist/`` directory (which is generated by running ``grunt`` -in the ``bootstrap/`` directory) into ``ietf/static/ietf/bootstrap``, from -where it is collected by ``collectstatic``. - -Changes to Template Files -========================= - -In order to make the template files refer to the correct versioned CDN URL -(as given by the STATIC_URL root) all references to static files in the -templates have been updated to use the ``static`` template tag when referring -to static files. This will automatically result in both serving static files -from the right place in development mode, and referring to the correct -versioned URL in production mode and the simpler ``/static/`` urls in -development mode. - -.. _bootstrap: http://getbootstrap.com/ - -Deployment -========== - -During deployment, it is now necessary to run the management command:: - - $ ietf/manage.py collectstatic - -before activating a new release. - -The deployment ``README`` file at ``/a/www/ietf-datatracker/README`` has been -updated accordingly. diff --git a/README.datatracker b/README.datatracker deleted file mode 100644 index 5c1a77b28..000000000 --- a/README.datatracker +++ /dev/null @@ -1,35 +0,0 @@ -The "new" datatracker uses Twitter Bootstrap for the UI. - -Get familiar with http://getbootstrap.com/getting-started/ and use those -UI elements instead of cooking up your own. - -We have some site-wide customization applied to the bootstrap version we keep -in bootstrap/ (from which the minified dist version is built); it modifies -some stuff under less/ - -We also apply some additional customizations in static/css/ietf.css; we -should eventually move that under bootstrap/less/ if possible. (ietf.css was -what Lars used initially for customization with an unmodified bootstrap.) - -Some ground rules: - -* Think hard before tweaking the bootstrap CSS, it will make it harder to - upgrade to future releases. - -* No <style> tags in the HTML! Put CSS into the "morecss" block of a - template instead. - -* CSS that is used by multiple templates goes into static/css/ietf.css. - -* Javascript that is only used on one template goes into the "js" block of - that template. - -* Javascript that is used by multiple templates goes into static/js/ietf.js. - -* Every template includes jquery, so write jquery code and not plain Javascript. - It's shorter and often faster. - -* No CSS, HTML styling or Javascript in the python code! - -* Templates that use jquery or bootstrap plugins include the css file in the - "pagehead" block, and the Javascript in the "js" block. diff --git a/README.md b/README.md new file mode 100644 index 000000000..07803ad96 --- /dev/null +++ b/README.md @@ -0,0 +1,136 @@ +<div align="center"> + +<img src="media/docs/ietf-datatracker-logo.svg" alt="IETF Datatracker" width="600" /> + +[](https://github.com/ietf-tools/datatracker/releases) +[](https://github.com/ietf-tools/datatracker/blob/main/LICENSE) + + +##### The day-to-day front-end to the IETF database for people who work on IETF standards. + +</div> + +- [**Production Website**](https://datatracker.ietf.org) +- [Getting Started](#getting-started) + - [Prerequisites](#prerequisites) + - [Code Tree Overview](#code-tree-overview) + - [Adding a New Web Page](#adding-a-new-web-page) + - [Testing your work](#testing-your-work) +- [Docker Dev Environment](#docker-dev-environment) +- [Continuous Integration](#continuous-integration) +- [Database & Assets](#database--assets) + +--- + +### Getting Started + +This project is following the standard **Git Feature Workflow with Develop Branch** development model. Learn about all the various steps of the development workflow, from creating a fork to submitting a pull request, in the [Contributing](CONTRIBUTING.md) guide. + +> Make sure to read the [Styleguides](CONTRIBUTING.md#styleguides) section to ensure a cohesive code format across the project. + +You can submit bug reports, enhancement and new feature requests in the [discussions](https://github.com/ietf-tools/datatracker/discussions) area. Accepted tickets will be converted to issues. + +#### Prerequisites + +- Python 3.6 +- Django 2.x +- Node.js 16.x +- MariaDB 10 + +> See the [Docker Dev Environment](#docker-dev-environment) section below for a preconfigured docker environment. + +#### Code Tree Overview + +The `ietf/templates/` directory contains Django templates used to generate web pages for the datatracker, mailing list, wgcharter and other things. + +Most of the other `ietf` sub-directories, such as `meeting`, contain the python/Django model and view information that go with the related templates. In these directories, the key files are: + +| File | Description | +|--|--| +| urls.py | binds a URL to a view, possibly selecting some data from the model. | +| models.py | has the data models for the tool area. | +| views.py | has the views for this tool area, and is where views are bound to the template. | + +#### Adding a New Web Page + +To add a new page to the tools, first explore the `models.py` to see if the model you need already exists. Within `models.py` are classes such as: + +```python +class IETFWG(models.Model): + ACTIVE = 1 + group_acronym = models.ForeignKey(Acronym, primary_key=True, unique=True, editable=False) + group_type = models.ForeignKey(WGType) + proposed_date = models.DateField(null=True, blank=True) + start_date = models.DateField(null=True, blank=True) + dormant_date = models.DateField(null=True, blank=True) + ... +``` + +In this example, the `IETFWG` class can be used to reference various fields of the database including `group_type`. Of note here is that `group_acronym` is the `Acronym` model so fields in that model can be accessed (e.g., `group_acronym.name`). + +Next, add a template for the new page in the proper sub-directory of the `ietf/templates` directory. For a simple page that iterates over one type of object, the key part of the template will look something like this: + +```html +{% for wg in object_list %} +<tr> +<td><a href="{{ wg.email_archive }}">{{ wg }}</a></td> +<td>{{ wg.group_acronym.name }}</td> +</tr> +{% endfor %} +``` +In this case, we're expecting `object_list` to be passed to the template from the view and expecting it to contain objects with the `IETFWG` model. + +Then add a view for the template to `views.py`. A simple view might look like: + +```python +def list_wgwebmail(request): + wgs = IETFWG.objects.all(); + return render_to_response('mailinglists/wgwebmail_list.html', {'object_list': wgs}) +``` +The selects the IETFWG objects from the database and renders the template with them in object_list. The model you're using has to be explicitly imported at the top of views.py in the imports statement. + +Finally, add a URL to display the view to `urls.py`. For this example, the reference to `list_wgwebmail` view is called: + +```python +urlpatterns += patterns('', + ... + (r'^wg/$', views.list_wgwebmail), +) +``` + +#### Testing your work + +Assuming you have the database settings configured already, you can run the server locally with: + +```sh + $ ietf/manage.py runserver localhost:<port> + ``` +where `<port>` is arbitrary. Then connect your web browser to `localhost:<port>` and provide the URL to see your work. + +When you believe you are ready to commit your work, you should run the test suite to make sure that no tests break. You do this by running + +```sh + $ ietf/manage.py test --settings=settings_sqlitetest +``` + +### Docker Dev Environment + +In order to simplify and reduce the time required for setup, a preconfigured docker environment is available. + +Read the [Docker Dev Environment](docker/README.md) guide to get started. + +### Continuous Integration + +*TODO* + +### Database & Assets + +Nightly database dumps of the datatracker are available at +https://www.ietf.org/lib/dt/sprint/ietf_utf8.sql.gz + +> Note that this link is provided as reference only. To update the database in your dev environment to the latest version, you should instead run the `docker/cleandb` script! + +Additional data files used by the datatracker (e.g. instance drafts, charters, rfcs, agendas, minutes, etc.) are available at +https://www.ietf.org/standards/ids/internet-draft-mirror-sites/ + +> A script is available at `docker/scripts/app-rsync-extras.sh` to automatically fetch these resources via rsync. diff --git a/docker/_old/README.md b/docker/_old/README.md deleted file mode 100644 index fe5c9fff4..000000000 --- a/docker/_old/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# Datatracker Development in Docker - -## Getting started - -1. [Set up Docker](https://docs.docker.com/get-started/) on your preferred - platform. - -2. If you have a copy of the datatracker code checked out already, simply `cd` - to the top-level directory. - - If not, check out a datatracker branch as usual. We'll check out `trunk` - below, but you can use any branch: - - svn co https://svn.ietf.org/svn/tools/ietfdb/trunk - cd trunk - -3. **TEMPORARY:** Replace the contents of the `docker` directory with [Lars' - files](https://svn.ietf.org/svn/tools/ietfdb/personal/lars/7.39.1.dev0/docker/). - -4. **TEMPORARY:** Until [Lars' - changes](https://svn.ietf.org/svn/tools/ietfdb/personal/lars/7.39.1.dev0/docker/) - have been merged and a docker image is available for download, you will need - to build it locally: - - docker/build - - This will take a while, but only needs to be done once. - -5. Use the `docker/run` script to start the datatracker container. You will be - dropped into a shell from which you can start the datatracker and execute - related commands as usual, for example - - ietf/manage.py runserver 0.0.0.0:8000 - - to start the datatracker. - - You can also pass additional arguments to `docker/run`, in which case they - will be executed in the container (instead of a shell being started.) - - If you do not already have a copy of the IETF database available in the - `data` directory, one will be downloaded and imported the first time you run - `docker/run`. This will take some time. - - Once the datatracker has started, you should be able to open - [http://localhost:8000](http://localhost:8000) in a browser and see the - landing page. - -## Troubleshooting - -- If the database fails to start, the cause is usually an incompatibility - between the database that last touched the files in `data/mysql` and the - database running inside the docker container. - - The solution is to blow away your existing database (`rm -rf data/mysql`). A - fresh copy will be retrieved and imported next time you do `docker/run`, which - should resolve this issue. \ No newline at end of file diff --git a/docker/_old/run b/docker/_old/run deleted file mode 100644 index 79e7510cd..000000000 --- a/docker/_old/run +++ /dev/null @@ -1,110 +0,0 @@ -#!/bin/bash - -version=0.20 -program=${0##*/} -progdir=${0%/*} -if [ "$progdir" = "$program" ]; then progdir="."; fi -if [ "$progdir" = "." ]; then progdir="$PWD"; fi -parent=$(dirname "$progdir") -if [ "$parent" = "." ]; then parent="$PWD"; fi -if [[ $(uname) =~ CYGWIN.* ]]; then parent=$(echo "$parent" | sed -e 's/^\/cygdrive\/\(.\)/\1:/'); fi - - -function usage() { - cat <<EOF -NAME - $program - Run a docker datatracker container with suitable settings - -SYNOPSIS - $program [OPTIONS] ARGS - -DESCRIPTION - This is a wrapper which runs an Ubuntu-based docker image which - has been set up with the dependencies needed to easily run the - IETF datatracker in development mode. - - MySQL database files at data/mysql will be used; if they do not exist, - a database dump will be retrieved and restored on first run. - -OPTIONS -EOF - grep -E '^\s+-[a-zA-Z])' "$0" | sed -E -e 's/\)[^#]+#/ /' - cat <<EOF - -AUTHOR - Written by: - Henrik Levkowetz, <henrik@levkowetz.com> - Lars Eggert, <lars@eggert.org> - -COPYRIGHT - Copyright (c) 2016 IETF Trust and the persons identified as authors of - the code. All rights reserved. Redistribution and use in source and - binary forms, with or without modification, is permitted pursuant to, - and subject to the license terms contained in, the Revised BSD - License set forth in Section 4.c of the IETF Trust’s Legal Provisions - Relating to IETF Documents(https://trustee.ietf.org/license-info). -EOF -} - - -function die() { - echo -e "\n$program: error: $*" >&2 - exit 1 -} - - -function version() { - echo -e "$program $version" -} - - -trap 'echo "$program($LINENO): Command failed with error code $? ([$$] $0 $*)"; exit 1' ERR - -# Default values -MYSQLDIR=$parent/data/mysql -PORT=8000 -REPO="ietf/datatracker-environment" -CACHED=':cached' - -# Option parsing -shortopts=cChp:V -args=$(getopt -o$shortopts $*) -if [ $? != 0 ] ; then die "Terminating..." >&2 ; exit 1 ; fi -set -- $args - -while true ; do - case "$1" in - -c) CACHED=':cached';; # Use cached disk access to reduce system load - -C) CACHED=':consistent';; # Use fully synchronized disk access - -h) usage; exit;; # Show this help, then exit - -p) PORT=$2; shift;; # Bind the container's port 8000 to external port PORT - -V) version; exit;; # Show program version, then exit - --) shift; break;; - *) die "Internal error, inconsistent option specification: '$1'";; - esac - shift -done - -if [ -z "$TAG" ]; then - TAG=$(basename "$(svn info "$parent" | grep ^URL | awk '{print $2}' | tr -d '\r')") -fi - -if [[ $(uname) =~ CYGWIN.* ]]; then - echo "Running under Cygwin, replacing symlinks with file copies" - ICSFILES=$(/usr/bin/find "$parent/vzic/zoneinfo/" -name '*.ics' -print) - for ICSFILE in $ICSFILES; do - LINK=$(head -n1 "$ICSFILE" | sed -e '/link .*/!d' -e 's/link \(.*\)/\1/') - if [ "$LINK" ]; then - WDIR=$(dirname "$ICSFILE") - echo "Replacing $(basename "$ICSFILE") with $LINK" - cp -f "$WDIR/$LINK" "$ICSFILE" - fi - done -fi - -echo "Starting a docker container for '$REPO:$TAG'." -mkdir -p "$MYSQLDIR" -docker run -ti -p "$PORT":8000 -p 33306:3306 \ - -v "$parent:/root/src$CACHED" \ - -v "$MYSQLDIR:/var/lib/mysql:delegated" \ - "$REPO:$TAG" "$@" \ No newline at end of file diff --git a/docker/scripts/updatedb b/docker/scripts/updatedb index d6d548453..85386daa4 100644 --- a/docker/scripts/updatedb +++ b/docker/scripts/updatedb @@ -1,105 +1,5 @@ #!/bin/bash -version=0.20 -program=${0##*/} -progdir=${0%/*} -if [ "$progdir" = "$program" ]; then progdir="."; fi -if [ "$progdir" = "." ]; then progdir="$PWD"; fi -parent=$(dirname "$progdir") -if [ "$parent" = "." ]; then parent="$PWD"; fi -if [[ $(uname) =~ CYGWIN.* ]]; then parent=$(echo "$parent" | sed -e 's/^\/cygdrive\/\(.\)/\1:/'); fi +echo "This script is deprecated. Please use the `cleandb` script in the parent folder instead." - -function usage() { - cat <<EOF -NAME - $program - Update the local copy of the IETF database from a dump - -SYNOPSIS - $program [OPTIONS] ARGS - -DESCRIPTION - This script downloads a dump of the IETF database and loads into the - local sql server if it is newer than the current dump. - -OPTIONS -EOF - grep -E '^\s+-[a-zA-Z])' "$0" | sed -E -e 's/\)[^#]+#/ /' - cat <<EOF - -AUTHOR - Written by: - Henrik Levkowetz, <henrik@levkowetz.com> - Lars Eggert, <lars@eggert.org> - -COPYRIGHT - Copyright (c) 2016 IETF Trust and the persons identified as authors of - the code. All rights reserved. Redistribution and use in source and - binary forms, with or without modification, is permitted pursuant to, - and subject to the license terms contained in, the Revised BSD - License set forth in Section 4.c of the IETF Trust’s Legal Provisions - Relating to IETF Documents(https://trustee.ietf.org/license-info). -EOF -} - - -function die() { - echo -e "\n$program: error: $*" >&2 - exit 1 -} - - -function version() { - echo -e "$program $version" -} - - -trap 'echo "$program($LINENO): Command failed with error code $? ([$$] $0 $*)"; exit 1' ERR - -# Option parsing -shortopts=DLZhV -LOAD=1 -DOWNLOAD=1 -DROP=1 - -args=$(getopt -o$shortopts $*) -if [ $? != 0 ] ; then die "Terminating..." >&2 ; exit 1 ; fi -set -- $args - -while true ; do - case "$1" in - -D) DOWNLOAD="";; # Don't download, use existing file - -L) LOAD=""; ;; # Don't load the database - -Z) DROP="";; # Don't drop new tables - -h) usage; exit;; # Show this help, then exit - -V) version; exit;; # Show program version, then exit - --) shift; break;; - *) die "Internal error, inconsistent option specification: '$1'";; - esac - shift -done - -# The program itself -DATADIR=$parent/data -DUMP=ietf_utf8.sql.gz -if [ "$DOWNLOAD" ]; then - echo "Fetching database dump..." - rsync --info=progress2 rsync.ietf.org::dev.db/$DUMP "$DATADIR" -fi - -if [ "$LOAD" ]; then - echo "Loading database..." - SIZE=$(pigz --list "$DATADIR/$DUMP" | tail -n 1 | awk '{ print $2 }') - pigz -d < "$DATADIR/$DUMP" \ - | pv --progress --bytes --rate --eta --size "$SIZE" \ - | sed -e 's/ENGINE=MyISAM/ENGINE=InnoDB/' \ - | "$parent/ietf/manage.py" dbshell -fi - -if [ "$DROP" ]; then - echo "Dropping tables not in the dump (so migrations can succeed)..." - diff <(pigz -d -c "$DATADIR/$DUMP" | grep '^DROP TABLE IF EXISTS' | tr -d '`;' | awk '{ print $5 }') \ - <("$parent/ietf/manage.py" dbshell <<< 'show tables;' | tail -n +2) \ - | grep '^>' | awk '{print "drop table if exists", $2, ";";}' \ - | tee >(cat >&2) | "$parent/ietf/manage.py" dbshell -fi \ No newline at end of file +# Modified on 2021-12-20, remove this file after a while \ No newline at end of file diff --git a/media/docs/ietf-datatracker-logo.svg b/media/docs/ietf-datatracker-logo.svg new file mode 100644 index 000000000..316b1ba59 --- /dev/null +++ b/media/docs/ietf-datatracker-logo.svg @@ -0,0 +1,82 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg width="100%" height="100%" viewBox="0 0 1024 250" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;"> + <g transform="matrix(1.39872,0,0,1.39872,-433.548,-258.273)"> + <text x="573px" y="304px" style="font-family:'SquadaOne-Regular', 'Squada One';font-size:96px;fill:url(#_Linear1);">DATATRACKER</text> + </g> + <g transform="matrix(1,0,0,1,0,-90)"> + <g transform="matrix(0.0384615,0,0,1,323.077,0)"> + <rect x="336" y="90" width="26" height="247" style="fill:url(#_Linear2);"/> + </g> + <g transform="matrix(0.0384615,0,0,1,324.077,0)"> + <rect x="336" y="90" width="26" height="247" style="fill:url(#_Linear3);"/> + </g> + </g> + <g transform="matrix(0.60874,0,0,0.60874,-179.578,38.2694)"> + <g id="squares" transform="matrix(1,0,0,1,295,5)"> + <g transform="matrix(0.707107,-0.707107,0.707107,0.707107,-270.59,-94.37)"> + <rect x="77.53" y="317.2" width="48.94" height="48.94" style="fill:rgb(188,190,192);"/> + </g> + <g transform="matrix(0.707107,-0.707107,0.707107,0.707107,-151.08,194.17)"> + <rect x="485.59" y="317.2" width="48.94" height="48.94" style="fill:rgb(188,190,192);"/> + </g> + <g transform="matrix(0.707107,-0.707107,0.707107,0.707107,-246.72,-36.73)"> + <rect x="159.04" y="317.2" width="48.94" height="48.94" style="fill:rgb(188,190,192);"/> + </g> + <g transform="matrix(0.707107,-0.707107,0.707107,0.707107,-222.85,20.9)"> + <rect x="240.54" y="317.2" width="48.94" height="48.94" style="fill:rgb(188,190,192);"/> + </g> + <g transform="matrix(0.707107,-0.707107,0.707107,0.707107,-198.98,78.53)"> + <rect x="322.05" y="317.2" width="48.94" height="48.94" style="fill:rgb(188,190,192);"/> + </g> + <g transform="matrix(0.707107,-0.707107,0.707107,0.707107,-175.11,136.16)"> + <rect x="403.55" y="317.2" width="48.94" height="48.94" style="fill:rgb(188,190,192);"/> + </g> + <g transform="matrix(0.707107,-0.707107,0.707107,0.707107,-263.62,4.28)"> + <rect x="200.09" y="358.11" width="48.94" height="48.94" style="fill:rgb(188,190,192);"/> + </g> + <g transform="matrix(0.707107,-0.707107,0.707107,0.707107,-239.75,61.9)"> + <rect x="281.59" y="358.11" width="48.94" height="48.94" style="fill:rgb(188,190,192);"/> + </g> + <g transform="matrix(0.707107,-0.707107,0.707107,0.707107,-215.88,119.53)"> + <rect x="363.09" y="358.11" width="48.94" height="48.94" style="fill:rgb(188,190,192);"/> + </g> + <g transform="matrix(0.707107,-0.707107,0.707107,0.707107,-206.06,-19.57)"> + <rect x="200.09" y="276.7" width="48.94" height="48.94" style="fill:rgb(188,190,192);"/> + </g> + <g transform="matrix(0.707107,-0.707107,0.707107,0.707107,-182.19,38.06)"> + <rect x="281.59" y="276.7" width="48.94" height="48.94" style="fill:rgb(188,190,192);"/> + </g> + <g transform="matrix(0.707107,-0.707107,0.707107,0.707107,-158.32,95.69)"> + <rect x="363.09" y="276.7" width="48.94" height="48.94" style="fill:rgb(188,190,192);"/> + </g> + </g> + <g id="line" transform="matrix(1,0,0,1,295,5)"> + <path d="M14.49,71.07L85.72,71.07L124.93,110.28L165.43,69.79L206.14,110.51L287.98,28.67L328.9,69.59L369.39,29.1L411.79,71.5L481.33,71.5L481.33,79.55L408.4,79.55L369.18,40.33L328.47,81.04L287.77,40.33L206.36,121.74L165.65,81.04L125.16,121.53L82.54,78.92L14.06,78.92L14.49,71.07Z" style="fill:rgb(255,210,79);fill-rule:nonzero;stroke:black;stroke-width:1.5px;"/> + <rect x="0" y="67.79" width="16.54" height="15.26" style="fill:rgb(35,31,32);"/> + <rect x="476.49" y="67.79" width="16.54" height="15.26" style="fill:rgb(35,31,32);"/> + </g> + <g id="text" transform="matrix(1,0,0,1,295,5)"> + <g transform="matrix(1,0,0,1,-58.87,-266.56)"> + <rect x="73.39" y="479" width="20.21" height="57.67" style="fill:rgb(35,31,32);fill-rule:nonzero;"/> + </g> + <g transform="matrix(1,0,0,1,-58.87,-266.56)"> + <path d="M198.8,479L242,479L242,491.18L219,491.18L219,501.33L240.05,501.33L240.05,513.5L219,513.5L219,524.5L242.34,524.5L242.34,536.67L198.8,536.67L198.8,479Z" style="fill:rgb(35,31,32);fill-rule:nonzero;"/> + </g> + <g transform="matrix(1,0,0,1,-58.87,-266.56)"> + <path d="M341.62,493.44L341.62,479L397.86,479L397.86,493.46L379.86,493.46L379.86,536.67L359.64,536.67L359.64,493.44L341.62,493.44Z" style="fill:rgb(35,31,32);fill-rule:nonzero;"/> + </g> + <g transform="matrix(1,0,0,1,-58.87,-266.56)"> + <path d="M499.08,479L541.19,479L541.19,491.18L519.29,491.18L519.29,501.66L539.84,501.66L539.84,513.84L519.29,513.84L519.29,536.67L499.08,536.67L499.08,479Z" style="fill:rgb(35,31,32);fill-rule:nonzero;"/> + </g> + <g transform="matrix(1,0,0,1,-58.87,-266.56)"> + <path d="M558.87,478.4C563.995,478.405 568.21,482.625 568.21,487.75C568.21,492.879 563.989,497.1 558.86,497.1C553.735,497.1 549.515,492.885 549.51,487.76C549.51,482.625 553.735,478.4 558.87,478.4ZM558.87,495.29C562.999,495.279 566.39,491.879 566.39,487.75C566.39,483.614 562.986,480.21 558.85,480.21C554.714,480.21 551.31,483.614 551.31,487.75C551.31,487.753 551.31,487.757 551.31,487.76C551.321,491.898 554.732,495.295 558.87,495.29ZM560.8,492.73L559.97,491.12C559.07,489.37 558.36,488.64 557.34,488.64L556.66,488.64L556.66,492.73L554.66,492.73L554.66,482.73L559.66,482.73C559.723,482.726 559.787,482.724 559.85,482.724C561.381,482.724 562.641,483.984 562.641,485.515C562.641,486.975 561.496,488.201 560.04,488.3L560.04,488.35C560.89,488.65 561.09,488.9 562.15,490.68L563.32,492.68L560.8,492.73ZM558.62,487.06C559.92,487.06 560.62,486.53 560.62,485.68C560.62,484.83 559.94,484.32 558.54,484.32L556.71,484.32L556.71,487.06L558.62,487.06Z" style="fill:rgb(35,31,32);fill-rule:nonzero;"/> + </g> + </g> + </g> + <defs> + <linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(4.92112e-15,80.368,-7.5457,4.62041e-16,939.048,235.264)"><stop offset="0" style="stop-color:rgb(61,0,121);stop-opacity:1"/><stop offset="1" style="stop-color:black;stop-opacity:1"/></linearGradient> + <linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.51244e-14,247,-247,1.51244e-14,349,90)"><stop offset="0" style="stop-color:white;stop-opacity:1"/><stop offset="0.5" style="stop-color:rgb(199,199,199);stop-opacity:1"/><stop offset="1" style="stop-color:white;stop-opacity:1"/></linearGradient> + <linearGradient id="_Linear3" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.51244e-14,247,-247,1.51244e-14,349,90)"><stop offset="0" style="stop-color:white;stop-opacity:1"/><stop offset="0.5" style="stop-color:rgb(146,146,146);stop-opacity:1"/><stop offset="1" style="stop-color:white;stop-opacity:1"/></linearGradient> + </defs> +</svg>