Attaching files

Other than photos, you may also need to get video or audio files from performers. In this case, you can add blocks for attaching the necessary files.

See what this looks like in the example of the "Monitoring items in businesses" template

Before:

After:

For your convenience, here is ready-made code for the “Monitoring items at businesses” template, in which each of the fields is added to the first response button once. Use it to check your own code. You can find our additions to the code by searching for the word “customization”.

Ready-made code
{{#if reviewMode}}
    <div class="header-review">
        <div class="header-review__title">
            {{texts.task_title}}
        </div>
        <div class="header-review__buttons">
            {{#if (equal verdict "ok")}}
                <div class="header-review__btn header-review__btn_green">
                    {{texts.btn_ok.title}}
                </div>
            {{/if}}
            {{#if (equal verdict "no_obj")}}
                <div class="header-review__btn header-review__btn_red">
                    {{texts.btn_no_obj.title}}
                </div>
            {{/if}}
            {{#if (equal verdict "no_org")}}
                <div class="header-review__btn header-review__btn_red">
                    {{texts.btn_no_org.title}}
                </div>
            {{/if}}
        </div>
    </div>
{{else}}
    <div class="header">
        {{texts.task_title}}
    </div>
{{/if}}

<div class="info">
    {{#if reviewMode}}
        <div class="info__review">
            <div class="info__review-block">
                <div class="info__title">
                    {{texts.info_name}}
                </div>
                <div class="info__content">
                    {{name}}
                </div>
            </div>
            <div class="info__review-block">
                <div class="info__title">
                    {{texts.info_address}}
                </div>
                <div class="info__content">
                    {{address}}
                </div>
            </div>
        </div>
    {{else}}
        <div class="info__block">
            <div class="info__title">
                {{texts.info_name}}
            </div>
            <div class="info__content">
                {{name}}
            </div>
        </div>
        <div class="info__block">
            <div class="info__title">
                {{texts.info_address}}
            </div>
            <div class="info__content">
                {{address}}
            </div>
        </div>
    {{/if}}
    <div class="info__block">
        <div class="info__title">
            {{texts.info_description}}
        </div>
        <div class="info__content">
            {{product}}
        </div>
    </div>
    <div class="info__block">
        <div class="info__content">
            <a href={{image}} target="_blank" class="info__link">Link to the product image</a>
        </div>
    </div>
</div>

{{#if reviewMode}}
    <div class="review">
        <div class="review__map">
            <div id="{{concat 'map_' id}}" style="width: 100%; height: 400px;"></div>
        </div>
        {{#if (equal verdict "ok")}}
            <div class="review__block">
                <div class="review__title">
                    {{texts.btn_ok.question_1.title}}
                </div>
                <div class="review__imgs-grid">
                    {{#each imgs_facade}}
                        <div class="review__grid-item">
                            <div class="review__grid-inner">
                                <img src="{{this}}" class="review__img" data-rotationdeg="0">
                                <div class="review__rotate-panel">
                                    <span class="review__rotate review__rotate_left">←</span>
                                    <span class="review__rotate review__rotate_right">→</span>
                                </div>
                            </div>
                        </div>
                    {{/each}}
                </div>
            </div>
            <div class="review__block">
                <div class="review__title">
                    {{texts.btn_ok.question_2.title}}
                </div>
                <div class="review__imgs-grid">
                    {{#each imgs_obj}}
                        <div class="review__grid-item">
                            <div class="review__grid-inner">
                                <img src="{{this}}" class="review__img" data-rotationdeg="0">
                                <div class="review__rotate-panel">
                                    <span class="review__rotate review__rotate_left">←</span>
                                    <span class="review__rotate review__rotate_right">→</span>
                                </div>
                            </div>
                        </div>
                    {{/each}}
                </div>
            </div>

            <!-- customization fragment start -->
            <!-- photo -->
            <div class="review__block">
              <div class="review__title">
                {{texts.btn_ok.question_new_imgs.title}}
              </div>
              <div class="review__imgs-grid">
                {{#each new_imgs}}
                  <div class="review__grid-item">
                    <div class="review__grid-inner">
                      <img src="{{this}}" class="review__img" data-rotationdeg="0">
                      <div class="review__rotate-panel">
                        <span class="review__rotate review__rotate_left">←</span>
                        <span class="review__rotate review__rotate_right">→</span>
                      </div>
                    </div>
                  </div>
                {{/each}}
              </div>
            </div>
            
            <!-- video -->
            <div class="review__block">
              <div class="review__title">
                {{texts.btn_ok.question_new_video.title}}
              </div>
              <div class="review__video-grid">
                {{#each new_video}}
                  <div class="review__video-grid-item">
                    <video width="50%" controls>
                      <source src={{this}} type="video/mp4">        
                    </video>
                  </div>    
                {{/each}}
              </div>
            </div>
            
            <!-- audio -->
            <div class="review__block">
              <div class="review__title">
                {{texts.btn_ok.question_new_audio.title}}
              </div>
              <div class="review__audio-grid">
                {{#each new_audio}}
                  <div class="review__audio-grid-item">
                    <audio src={{this}} controls type="audio/wav">Audio doesn't play</audio>
                  </div>    
                {{/each}}
              </div>
            </div>
            <!-- customization fragment end -->

        {{/if}}
        {{#if (equal verdict "no_obj")}}
            <div class="review__block">
                <div class="review__title">
                    {{texts.btn_no_obj.question_1.title}}
                </div>
                <div class="review__imgs-grid">
                    {{#each imgs_facade}}
                        <div class="review__grid-item">
                            <div class="review__grid-inner">
                                <img src="{{this}}" class="review__img" data-rotationdeg="0">
                                <div class="review__rotate-panel">
                                    <span class="review__rotate review__rotate_left">←</span>
                                    <span class="review__rotate review__rotate_right">→</span>
                                </div>
                            </div>
                        </div>
                    {{/each}}
                </div>
            </div>
            <div class="review__block">
                <div class="review__title">
                    {{texts.btn_no_obj.question_2.title}}
                </div>
                <div class="review__imgs-grid">
                    {{#each imgs_plate_or_address}}
                        <div class="review__grid-item">
                            <div class="review__grid-inner">
                                <img src="{{this}}" class="review__img" data-rotationdeg="0">
                                <div class="review__rotate-panel">
                                    <span class="review__rotate review__rotate_left">←</span>
                                    <span class="review__rotate review__rotate_right">→</span>
                                </div>
                            </div>
                        </div>
                    {{/each}}
                </div>
            </div>
            <div class="review__block">
                <div class="review__title">
                    {{texts.btn_no_obj.question_3.title}}
                </div>
                <div class="review__imgs-grid">
                    {{#each imgs_around_obj}}
                        <div class="review__grid-item">
                            <div class="review__grid-inner">
                                <img src="{{this}}" class="review__img" data-rotationdeg="0">
                                <div class="review__rotate-panel">
                                    <span class="review__rotate review__rotate_left">←</span>
                                    <span class="review__rotate review__rotate_right">→</span>
                                </div>
                            </div>
                        </div>
                    {{/each}}
                </div>
            </div>
            {{#if comment}}
                <div class="review__block">
                    <div class="review__title">
                        {{texts.btn_no_obj.question_4.title}}
                    </div>
                    <div class="review__comment">
                        {{field type="textarea" name="comment" width="100%" rows=5}}
                    </div>
                </div>
            {{/if}}
        {{/if}}
        {{#if (equal verdict "no_org")}}
            <div class="review__block">
                <div class="review__title">
                    {{texts.btn_no_org.question_1.title}}
                </div>
                <div class="review__imgs-grid">
                    {{#each imgs_around_org}}
                        <div class="review__grid-item">
                            <div class="review__grid-inner">
                                <img src="{{this}}" class="review__img" data-rotationdeg="0">
                                <div class="review__rotate-panel">
                                    <span class="review__rotate review__rotate_left">←</span>
                                    <span class="review__rotate review__rotate_right">→</span>
                                </div>
                            </div>
                        </div>
                    {{/each}}
                </div>
            </div>
            <div class="review__block">
                <div class="review__title">
                    {{texts.btn_no_org.question_2.title}}
                </div>
                <div class="review__imgs-grid">
                    {{#each imgs_plate_or_address}}
                        <div class="review__grid-item">
                            <div class="review__grid-inner">
                                <img src="{{this}}" class="review__img" data-rotationdeg="0">
                                <div class="review__rotate-panel">
                                    <span class="review__rotate review__rotate_left">←</span>
                                    <span class="review__rotate review__rotate_right">→</span>
                                </div>
                            </div>
                        </div>
                    {{/each}}
                </div>
            </div>
            <div class="review__block">
                <div class="review__title">
                    {{texts.btn_no_org.question_3.title}}
                </div>
                <div class="review__comment">
                    {{field type="textarea" name="comment" width="100%" rows=5}}
                </div>
            </div>
        {{/if}}
    </div>
{{else}}
    <div class="main">
        <div class="main__title">
            Select a task completion option:
        </div>
        <div class="main__container">
            <div class="main__popup main__popup_hidden">No answer selected</div>
            <div class="main__block">
                <div class="main__btn main__btn_green">
                    {{texts.btn_ok.title}}
                </div>
                <div class="main__content">
                    <div class="main__content-block">
                        <div class="main__content-title main__content-title_req">
                            {{texts.btn_ok.question_1.title}}
                        </div>
                        <div class="main__text">
                            {{texts.btn_ok.question_1.description}}
                        </div>
                        <div class="main__ex">
                            <a href="{{texts.btn_ok.question_1.example_link_1}}" target="_blank" class="main__ex-link">Example</a>
                        </div>
                        <div class="main__imgs">
                            {{field type="file-img" name="imgs_facade" camera=true preview=true compress=false validation-show="top-left"}}
                        </div>
                    </div>
                    <div class="main__content-block">
                        <div class="main__content-title main__content-title_req">
                            {{texts.btn_ok.question_2.title}}
                        </div>
                        <div class="main__text">
                            {{texts.btn_ok.question_2.description}}
                        </div>
                        <div class="main__ex">
                            <a href="{{texts.btn_ok.question_2.example_link_1}}" target="_blank" class="main__ex-link">Example</a>
                        </div>
                        <div class="main__imgs">
                            {{field type="file-img" name="imgs_obj" camera=true preview=true compress=false validation-show="top-left"}}
                        </div>
                    </div>

                    <!-- customization fragment start -->
            <!-- photo -->
                    <div class="main__content-block">
                      <div class="main__content-title main__content-title_req">
                        {{texts.btn_ok.question_new_imgs.title}}
                      </div>
                      <div class="main__text">
                        {{texts.btn_ok.question_new_imgs.description}}
                      </div>
                      <div class="main__ex">
                        <a href="{{texts.btn_ok.question_new_imgs.example_link_1}}" target="_blank" class="main__ex-link">Example</a>
                      </div>
                      <div class="main__imgs">
                        {{field type="file-img" name="new_imgs" camera=true validation-show="top-left"}}
                      </div>          
                    </div>

                    <!-- video -->
                    <div class="main__content-block">
                      <div class="main__content-title main__content-title_req">
                        {{texts.btn_ok.question_new_video.title}}
                      </div>
                      <div class="main__text">
                        {{texts.btn_ok.question_new_video.description}}
                      </div>
                      <div class="main__video">
                        {{field type="file" name="new_video" sources="CAMERA GALLERY" fileType="VIDEO" camera=true validation-show="top-left"}}
                      </div>          
                    </div>

                    <!-- audio -->
                    <div class="main__content-block">
                      <div class="main__content-title main__content-title_req">
                        {{texts.btn_ok.question_new_audio.title}}
                      </div>
                      <div class="main__text">
                        {{texts.btn_ok.question_new_audio.description}}
                      </div>
                      <div class="main__audio">
                        {{field type="file" name="new_audio" sources="RECORDER FILE_MANAGER" fileType="AUDIO" validation-show="top-left"}}
                      </div>          
                    </div>
                    <!-- customization fragment end -->

                </div>
            </div>
            <div class="main__block">
                <div class="main__btn main__btn_red">
                    {{texts.btn_no_obj.title}}
                </div>
                <div class="main__content">
                    <div class="main__content-block">
                        <div class="main__content-title main__content-title_req">
                            {{texts.btn_no_obj.question_1.title}}
                        </div>
                        <div class="main__text">
                            {{texts.btn_no_obj.question_1.description}}
                        </div>
                        <div class="main__ex">
                            <a href="{{texts.btn_no_obj.question_1.example_link_1}}" target="_blank" class="main__ex-link">Example</a>
                        </div>
                        <div class="main__imgs">
                            {{field type="file-img" name="imgs_facade" camera=true validation-show="top-left"}}
                        </div>
                    </div>
                    <div class="main__content-block">
                        <div class="main__content-title main__content-title_req">
                            {{texts.btn_no_obj.question_2.title}}
                        </div>
                        <div class="main__text">
                            {{texts.btn_no_obj.question_2.description}}
                        </div>
                        <div class="main__ex">
                            <a href="{{texts.btn_no_obj.question_2.example_link_1}}" target="_blank" class="main__ex-link">Example</a>
                        </div>
                        <div class="main__imgs">
                            {{field type="file-img" name="imgs_plate_or_address" camera=true validation-show="top-left"}}
                        </div>
                    </div>
                    <div class="main__content-block">
                        <div class="main__content-title main__content-title_req">
                            {{texts.btn_no_obj.question_3.title}}
                        </div>
                        <div class="main__text">
                            {{texts.btn_no_obj.question_3.description}}
                        </div>
                        <div class="main__ex">
                            <a href="{{texts.btn_no_obj.question_3.example_link_1}}" target="_blank" class="main__ex-link">Example</a>
                        </div>
                        <div class="main__imgs">
                            {{field type="file-img" name="imgs_around_obj" camera=true validation-show="top-left"}}
                        </div>
                    </div>
                    <div class="main__content-block">
                        <div class="main__content-title">
                            {{texts.btn_no_obj.question_4.title}}
                        </div>
                        <div class="main__text">
                            {{texts.btn_no_obj.question_4.description}}
                        </div>
                        <div class="main__comment">
                            {{field type="textarea" name="comment" width="100%" rows=5 validation-show="top-left"}}
                        </div>
                    </div>
                </div>
            </div>
            <div class="main__block">
                <div class="main__btn main__btn_red">
                    {{texts.btn_no_org.title}}
                </div>
                <div class="main__content">
                    <div class="main__content-block">
                        <div class="main__text main__text_req">
                            {{texts.btn_no_org.question_1.description}}
                        </div>
                        <div class="main__imgs">
                            {{field type="file-img" name="imgs_around_org" camera=true validation-show="top-left"}}
                        </div>
                    </div>
                    <div class="main__content-block">
                        <div class="main__text main__text_req">
                            {{texts.btn_no_org.question_2.description}}
                        </div>
                        <div class="main__ex">
                            <a href="{{texts.btn_no_org.question_2.example_link_1}}" target="_blank" class="main__ex-link">Example</a>
                        </div>
                        <div class="main__imgs">
                            {{field type="file-img" name="imgs_plate_or_address" camera=true validation-show="top-left"}}
                        </div>
                    </div>
                    <div class="main__content-block">
                        <div class="main__content-title main__content-title_req">
                            {{texts.btn_no_org.question_3.title}}
                        </div>
                        <div class="main__text">
                            {{texts.btn_no_org.question_3.description}}
                        </div>
                        <div class="main__comment">
                            {{field type="textarea" name="comment" width="100%" rows=5 validation-show="top-left"}}
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
{{/if}}
Editing the output specification

Add new variables of the “file” type to the output specification. They will be used to save the files uploaded by the performer. If you want the performer to be able to upload more than one file, set the variable type to “array”.

imgs — An array of photos.

new_video — An array of video files.

new_audio — An array of audio files.

Special components are used to upload files. You can read more about them in the following sections:

Button for image upload

Button for recording and uploading a video file

Button for recording and uploading an audio file
Editing HTML
  1. The HTML code consists of blocks describing various interface elements. Each block may contain other blocks within it. There may be several nesting levels. For example, the block with a response button description contains other blocks with input fields. Each field contains other elements, such as a title and a comment field.

    Each block looks like this:

    <div class="block_name">
      <!-- code for the block that may contain nested blocks -->
      ...
    </div>
  2. Find the main block (it starts with <div class="main">). It contains several main_block blocks within it, each describing one of the buttons. For example, the “Monitoring items in businesses” template has 3 response buttons, which means that the main block should contain 3 main__block blocks for the buttons.

    Each button has a name for accessing its properties. For example, in the “Monitoring items in businesses” template, the buttons are named btn_ok, btn_no_obj, and btn_no_org. Remember the name of the button that you are adding new fields to in the code.

    The main_content block inside main__block contains all the fields for the selected button. The description of each field is located in main__content-block.

    Find the button in the main__block block, then find the main__content-block field where you want to add a new field and paste the following code after it:

    <!-- photo -->
    <div class="main__content-block">
      <div class="main__content-title main__content-title_req">
        {{texts.btn_ok.question_new_imgs.title}}
      </div>
      <div class="main__text">
        {{texts.btn_ok.question_new_imgs.description}}
      </div>
      <div class="main__ex">
        <a href="{{texts.btn_ok.question_new_imgs.example_link_1}}" target="_blank" class="main__ex-link">Example</a>
      </div>
      <div class="main__imgs">
        {{field type="file-img" name="new_imgs" camera=true validation-show="top-left"}}
      </div>          
    </div>
    
    <!-- video -->
    <div class="main__content-block">
      <div class="main__content-title main__content-title_req">
        {{texts.btn_ok.question_new_video.title}}
      </div>
      <div class="main__text">
        {{texts.btn_ok.question_new_video.description}}
      </div>
      <div class="main__video">
        {{field type="file" name="new_video" sources="CAMERA GALLERY" fileType="VIDEO" camera=true validation-show="top-left"}}
      </div>          
    </div>
    
    <!-- audio -->
    <div class="main__content-block">
      <div class="main__content-title main__content-title_req">
        {{texts.btn_ok.question_new_audio.title}}
      </div>
      <div class="main__text">
        {{texts.btn_ok.question_new_audio.description}}
      </div>
      <div class="main__audio">
        {{field type="file" name="new_audio" sources="RECORDER FILE_MANAGER" fileType="AUDIO" validation-show="top-left"}}
      </div>          
    </div>

    In this code, new fields are added for the first button with the name btn_ok. If you added fields to another button, replace btn_ok with the relevant button's name.

  3. Update the acceptance mode.

    The review block contains the code for each button in the acceptance mode. This code is located in the following blocks:

    {{#if (equal verdict "ok")}}
      <!-- code for the "ok" button in acceptance mode -->
      <div class="review__block">
        <!-- code for the "ok" button field in acceptance mode -->
        ...
      </div>
      ...
    {{/if}}

    The value of the response button selected by the performer is passed to the verdict variable specified in the output specification.

    For example, in the “Monitoring items in businesses” template, three output values are described for three buttons: ok, no_obj, and no_org.

    The review__block blocks contain a description of each field for this button.

    Find the button by searching for the string {{#if (equal verdict "response_button_value")}}, then find the review__block field where you want to add a new field and insert the following code after it:

    <!-- photo -->
    <div class="review__block">
      <div class="review__title">
        {{texts.btn_ok.question_new_imgs.title}}
      </div>
      <div class="review__imgs-grid">
        {{#each new_imgs}}
          <div class="review__grid-item">
            <div class="review__grid-inner">
              <img src="{{this}}" class="review__img" data-rotationdeg="0">
              <div class="review__rotate-panel">
                <span class="review__rotate review__rotate_left">←</span>
                <span class="review__rotate review__rotate_right">→</span>
              </div>
            </div>
          </div>
        {{/each}}
      </div>
    </div>
    
    <!-- video -->
    <div class="review__block">
      <div class="review__title">
        {{texts.btn_ok.question_new_video.title}}
      </div>
      <div class="review__video-grid">
        {{#each new_video}}
          <div class="review__video-grid-item">
            <video width="50%" controls>
              <source src={{this}} type="video/mp4">        
            </video>
          </div>    
        {{/each}}
      </div>
    </div>
    
    <!-- audio -->
    <div class="review__block">
      <div class="review__title">
        {{texts.btn_ok.question_new_audio.title}}
      </div>
      <div class="review__audio-grid">
        {{#each new_audio}}
          <div class="review__audio-grid-item">
            <audio src={{this}} controls type="audio/wav">Audio doesn't play</audio>
          </div>    
        {{/each}}
      </div>
    </div>

    In this code, new fields are added for the first button with the name btn_ok. If you added fields to another button, replace btn_ok with the relevant button's name.

Editing JS
  1. The JS code consists of blocks describing various interface elements. These blocks can be nested (buttons contain a set of fields, fields contain a set of elements, and so on). Each block is enclosed in curly brackets.

    The elements are described as follows:

    'property': 'value'

    The value can also consist of several properties, in which case it is enclosed in curly brackets and forms the next level of nesting.

  2. The texts constant at the very beginning of the file stores all texts for each button.

    Each button has a name for accessing its properties. For example, in the “Monitoring items in businesses” template, the buttons are named btn_ok, btn_no_obj, and btn_no_org. Remember the name of the button that you are adding new text to in the code.

    For example, in the “Monitoring items in businesses” template, the texts for the btn_ok button are located in the following code block:

    var texts = {
        //<common header text>
        'btn_ok': {
            'title': 'I found the object',
            'question_1': {
                //<texts for the first field (photos of the organization's facade)>
            },
            'question_2': {
                //<texts for the second field (object photos)>
            }
        },
  3. To add the texts, put a comma after the curly bracket that closes the last field and paste the following code:

    'question_new_imgs': {
      'title': 'Photos',
      'description': 'Take at least 2 photos',
      'example_link_1': 'link to an example of a photo'
    },
    'question_new_video': {
      'title': 'Video',
      'description': 'Record a video'
    },
    'question_new_audio': {
      'title': 'Audio',
      'description': 'Record an audio'
    }
  4. Find the getTemplateData function. It contains several blocks that look like this:

    if (<field checking condition>) {
        ...
        <code for displaying the uploaded data>
        ...
    }

    Paste the following code after any of these blocks. It is used to send the photos, videos, and audio files uploaded by the performer to the input data. You need this to display the data in the acceptance mode:

    // photo
    if (outputValues.new_imgs && outputValues.new_imgs.length > 0) {
      data.new_imgs = [];
      for (var i = 0; i < outputValues.new_imgs.length; i++) {
        data.new_imgs.push(workspaceOptions.apiOrigin + '/api/attachments/' + outputValues.new_imgs[i] + '/preview');
      }
    }
    
    // video
    if (outputValues.new_video && outputValues.new_video.length > 0) {
      data.new_video = [];
      for (var i = 0; i < outputValues.new_video.length; i++) {
        data.new_video.push(workspaceOptions.apiOrigin + '/api/attachments/' + outputValues.new_video[i] + '/preview');
      }
    }
    
    // audio
    if (outputValues.new_audio && outputValues.new_audio.length > 0) {
      data.new_audio = [];
      for (var i = 0; i < outputValues.new_audio.length; i++) {
        data.new_audio.push(workspaceOptions.apiOrigin + '/api/attachments/' + outputValues.new_audio[i] + '/preview');
      }
    }
  5. Add validation.

    Find the validate function. It contains the code for checking whether the fields in each of the buttons are filled in. For example, in the “Monitoring items in businesses” template, the code looks like this:

    if (!solution.output_values.verdict || solution.output_values.verdict === '') {
        this.errors = this.addError('No answer selected', "verdict", this.errors);
    } else if (solution.output_values.verdict === 'ok') {
        // code for checking the ok button fields
        if (!solution.output_values.imgs_facade || solution.output_values.imgs_facade.length === 0) {
            // code for checking the imgs_facade field
        }
    
        if (!solution.output_values.imgs_obj || solution.output_values.imgs_obj.length === 0) {
            // code for checking the imgs_obj field
        }
    
    } else if (solution.output_values.verdict === 'no_obj') {
        // code for checking the no_obj button fields
    } else if (solution.output_values.verdict === 'no_org') {
        // code for checking the no_org button fields
    }

    The response values for the buttons in this example, which are passed to the verdict output variable, have the same names as in the acceptance mode update step: ok, no_obj, and no_org.

    Find the validation block for the button. Inside this block, after any of the field validation blocks that look like this,

    if (!solution... ) {
        // field validation code
    }

    add the following code:

    if (!solution.output_values.new_imgs || solution.output_values.new_imgs.length === 0) {
      this.errors = this.addError('Attach photos', "new_imgs", this.errors);
    } else if (solution.output_values.new_imgs.length < 2) {
      this.errors = this.addError('There must be at least 2 photos', "new_imgs", this.errors);
    }
    
    if (!solution.output_values.new_video || solution.output_values.new_video.length < 1) {
      this.errors = this.addError('Attach a video', 'new_video', this.errors);
    }
    
    if (!solution.output_values.new_audio || solution.output_values.new_audio.length < 1) {
      this.errors = this.addError('Attach an audio', 'new_audio', this.errors);
    } 
Editing CSS

At the end of the CSS code block, paste the styles for the new fields:

.review__video-grid {
  margin: 0px -10px;
}

.review__audio-grid {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -ms-flex-wrap: wrap;
      flex-wrap: wrap;
  margin: 0px -10px;
}

.review__audio-grid-item {
  margin: 10px;
}

.review__video-grid-item {
  margin: 10px;
}

.main__video .field,
.main__audio .field {
  white-space: normal;
}

.main__video .field_file__files__file,
.main__audio .field_file__files__file {
  margin-bottom: 10px;
}