<commit_before>import {Modal} from './modal.js';
import {AnnotatedFields, getAnnotatedFieldFromDisplay} from './fields.js';
import {Loading} from './loading.js';

class BulkUpdateModal {
  constructor(modalId) {
    this.modal = new Modal(modalId, /*Blocking*/ true);

    // Used to give feedback/alerts to the user
    this.alertDiv = document.createElement('div');
    this.alertDiv.classList.add('alert');
  }

  populateAndShowModal(deviceIds, selectedValues, selectedFields, devicesCount) {
    let bodyElements = this.createModalBody(deviceIds, selectedValues, selectedFields, devicesCount);
    this.modal.setHeader('Perform Bulk Update');
    this.modal.setBody(bodyElements);
    this.modal.show();
  }

  createModalBody(deviceIds, selectedValues, selectedFields, devicesCount) {
    let warning = this.createModalWarning(devicesCount, selectedValues, selectedFields);
    let form = this.createModalForm(deviceIds, selectedValues, selectedFields);
    return [this.alertDiv, warning, form];
  }

  createModalForm(deviceIds, selectedValues, selectedFields) {
    let form = document.createElement('form');
    form.setAttribute('method', 'POST');
    form.setAttribute('action', '/update');

    form.addEventListener('submit', async (e) => {
      e.preventDefault();

      let loader = new Loading(this.submitForm.bind(this, form), false);
      let response = await loader.load();

      // TODO: Display a message to user depending on response
      this.alertUserSuccess();

      // Refresh the view when they exit
      this.modal.setRemoveCallback(() => {document.dispatchEvent(new CustomEvent('refreshData'))});
    });

    for (let i = 0; i < selectedValues.length; i++) {
      const aggregationField = selectedFields[i];
      const aggregationFieldValue = selectedValues[i];
      const apiAggregationFieldName = getAnnotatedFieldFromDisplay(aggregationField).API;

      let label = document.createElement('label');
      label.innerHTML = aggregationField;
      label.setAttribute('for', apiAggregationFieldName);
      label.classList.add('update-label');

      let input = document.createElement('input');
      input.setAttribute('type', 'text');
      input.setAttribute('value', aggregationFieldValue);
      input.setAttribute('name', apiAggregationFieldName);
      input.setAttribute('id', apiAggregationFieldName);
      input.classList.add('update-input');

      let container = document.createElement('div');
      container.appendChild(label);
      container.appendChild(input);

      form.appendChild(container);
    }

    let devicesInput = document.createElement('input');
    devicesInput.setAttribute('type', 'hidden');
    devicesInput.setAttribute('value', deviceIds);
    devicesInput.setAttribute('name', 'deviceIds');
    form.appendChild(devicesInput);

    let submit = document.createElement('input');
    submit.setAttribute('type', 'submit');
    form.appendChild(submit);

    return form;
  }

  async submitForm(form) {
    // Form Data encoding is not accepted by server so we need to convert it
    const data = new FormData(form);
    let body = new URLSearchParams();
    for (let pair of data) {
      body.append(pair[0], pair[1]);
    }

    await fetch(form.action, {
      method: form.method,
      body: body
    });
  }

  createModalWarning(devicesCount, selectedValues, selectedFields) {<commit_msg>Make more accessible by prompting screen reader to read alerts when updated.  Output status based on server response.<commit_after>import {Modal} from './modal.js';
import {AnnotatedFields, getAnnotatedFieldFromDisplay} from './fields.js';
import {Loading} from './loading.js';

class BulkUpdateModal {
  constructor(modalId) {
    this.modal = new Modal(modalId, /*Blocking*/ true);

    // Used to give feedback/alerts to the user
    this.alertDiv = document.createElement('div');
    this.alertDiv.classList.add('alert');
    this.alertDiv.setAttribute('aria-live', 'aggressive');
  }

  populateAndShowModal(deviceIds, selectedValues, selectedFields, devicesCount) {
    let bodyElements = this.createModalBody(deviceIds, selectedValues, selectedFields, devicesCount);
    this.modal.setHeader('Perform Bulk Update');
    this.modal.setBody(bodyElements);
    this.modal.show();
  }

  createModalBody(deviceIds, selectedValues, selectedFields, devicesCount) {
    let warning = this.createModalWarning(devicesCount, selectedValues, selectedFields);
    let form = this.createModalForm(deviceIds, selectedValues, selectedFields);
    return [this.alertDiv, warning, form];
  }

  createModalForm(deviceIds, selectedValues, selectedFields) {
    let form = document.createElement('form');
    form.setAttribute('method', 'POST');
    form.setAttribute('action', '/update');

    form.addEventListener('submit', async (e) => {
      e.preventDefault();

      let loader = new Loading(this.submitForm.bind(this, form), false);
      let response = await loader.load();

      // Refresh the view to reflect the updates.
      document.dispatchEvent(new CustomEvent('refreshData'));

      if (response.status == 200) {
        this.alertUserSuccess();
      } else {
        let json = await response.json();
        this.alertUserFailure(json.failedDevices);
      }
    });

    for (let i = 0; i < selectedValues.length; i++) {
      const aggregationField = selectedFields[i];
      const aggregationFieldValue = selectedValues[i];
      const apiAggregationFieldName = getAnnotatedFieldFromDisplay(aggregationField).API;

      let label = document.createElement('label');
      label.innerHTML = aggregationField;
      label.setAttribute('for', apiAggregationFieldName);
      label.classList.add('update-label');

      let input = document.createElement('input');
      input.setAttribute('type', 'text');
      input.setAttribute('value', aggregationFieldValue);
      input.setAttribute('name', apiAggregationFieldName);
      input.setAttribute('id', apiAggregationFieldName);
      input.classList.add('update-input');

      let container = document.createElement('div');
      container.appendChild(label);
      container.appendChild(input);

      form.appendChild(container);
    }

    let devicesInput = document.createElement('input');
    devicesInput.setAttribute('type', 'hidden');
    devicesInput.setAttribute('value', deviceIds);
    devicesInput.setAttribute('name', 'deviceIds');
    form.appendChild(devicesInput);

    let submit = document.createElement('input');
    submit.setAttribute('type', 'submit');
    form.appendChild(submit);

    return form;
  }

  async submitForm(form) {
    // Form Data encoding is not accepted by server so we need to convert it
    const data = new FormData(form);
    let body = new URLSearchParams();
    for (let pair of data) {
      body.append(pair[0], pair[1]);
    }

    return await fetch(form.action, {
      method: form.method,
      body: body
    });
  }

  createModalWarning(devicesCount, selectedValues, selectedFields) {
{'fraction_non_alphanumeric': 0.12449914138523183, 'fraction_numerical': 0.0012879221522610188, 'mean_word_length': 3.9497167138810196, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4722668', 'n_tokens_mistral': 1881, 'n_tokens_neox': 1856, 'n_words': 434}