<commit_before>function processRequest(request, sender, sendResponse) {
    preProcess();
    startAnnotation(request.data);
    chrome.runtime.onMessage.removeListener(processRequest);
}

function preProcess() {
    // while (document.body.firstChild) {
    //     document.body.firstChild.remove();
    // }
    var canvas = document.createElement("canvas");
    canvas.class = 'selectionBox';
    canvas.id = 'selectionBox';
    canvas.style = 'position: absolute; top: 0; left: 0; height: 0; width: 0; border: 1px solid red;';
    document.body.appendChild(canvas);
    // var selectDiv = document.createElement("div");
    // selectDiv.class = 'selectionBox';
    // selectDiv.style = 'position: absolute; top: 0; left: 0; height: 300; width: 300; border: 1px solid red;';
    // document.body.appendChild(selectDiv);
}

function startAnnotation(data) {

    if (!window.jQuery) {
        alert("JQ does NOT work");
    }
    //

    if ($('#selectionBox').length) {
        alert("Please select an area to annotate");
    } else {
        alert("Something is wrong with annotation selector");
    }
    // var html = document.documentElement;
    // html.className += " annotateClass";

    var mouse_down = false;

    var start_pos_x = 0;
    var start_pos_y = 0;
    var end_pos_x = 0;
    var end_pos_y = 0;

    $(function () {
        $('html').mousedown(function (e) {
            mouse_down = true;
            start_pos_x = e.pageX;
            start_pos_y = e.pageY;
        });

        $('html').mousemove(function (e) {
            end_pos_x = e.pageX;
            end_pos_y = e.pageY;

            if (mouse_down) {
                draw(start_pos_x, start_pos_y, end_pos_x, end_pos_y);
            }
        });

        $('html').mouseup(function (e) {
            end_pos_x = e.pageX;
            end_pos_y = e.pageY;

            if (mouse_down) {
                draw(start_pos_x, start_pos_y, end_pos_x, end_pos_y);
            }

            mouse_down = false;

            get_elements(start_pos_x, start_pos_y, end_pos_x, end_pos_y);
        });
    });

    function draw(x1, y1, x2, y2) {
        // console.log("Drawing top:" + x1 + ", left:" + x2 + ", width:" + (x2 - x1) + ", height:" + (y2 - y1));
        var canvas = document.getElementById('selectionBox');
        canvas.style = 'position: absolute; top: ' + y1 + 'px; left: ' + x1 + 'px; height: ' + (y2 - y1) + 'px; width: ' + (x2 - x1) + 'px; border: 1px solid blue;';
        // $('.selectionBox').css({
        //     'left': x1 + 'px',
        //     'top': y1 + 'px',
        //     'width': (x2 - x1) + 'px',
        //     'height': (y2 - y1) + 'px'
        // });
    }

    function get_elements(x1, y1, x2, y2) {
        // var element_list = '';
        //
        // $('#main *').each(function () {
        //     if (!($(this).attr('class') == 'selectionBox')) {
        //         var offset = $(this).offset();
        //
        //         var element_x1 = offset.left;
        //         var element_y1 = offset.top;
        //         var element_x2 = offset.left + $(this).width();
        //         var element_y2 = offset.top + $(this).height();
        //
        //         if (
        //             (
        //                 ((x1 >= element_x1 && x1 <= element_x2) && (y1 >= element_y1 && y1 <= element_y2)) ||
        //                 ((x2 >= element_x1 && x2 <= element_x2) && (y1 >= element_y1 && y1 <= element_y2)) ||
        //                 ((x2 >= element_x1 && x2 <= element_x2) && (y2 >= element_y1 && y2 <= element_y2)) ||
        //                 ((x1 >= element_x1 && x1 <= element_x2) && (y2 >= element_y1 && y2 <= element_y2))
        //             ) ||
        //             (
        //                 ((element_x1 >= x1 && element_x1 <= x2) && (element_y1 >= y1 && element_y1 <= y2)) ||
        //                 ((element_x2 >= x1 && element_x2 <= x2) && (element_y1 >= y1 && element_y1 <= y2)) ||
        //                 ((element_x2 >= x1 && element_x2 <= x2) && (element_y2 >= y1 && element_y2 <= y2)) ||
        //                 ((element_x1 >= x1 && element_x1 <= x2) && (element_y2 >= y1 && element_y2 <= y2))
        //             )
        //         ) {
        //             element_list += this.nodeName + ' -> ' + $(this).attr('class') + '
';
        //         }
        //     }
        // });
        //
        // $('.output').html(element_list);
        // return getElementsInRegion(x1,y1,x2-x1,y2-y1);
        function getElementsInRegion(x, y, width, height) {
            console.log("Selecting elements in region x,y:" + x + ", " + y + " , width:" + width + ", height:" + height);
            var elements = [],
                expando = +new Date,
                cx = x,
                cy = y,
                curEl;

            height = y + height;
            width = x + width;

            while ((cy += 5) < height) {
                cx = x;
                while (cx < width) {
                    curEl = document.elementFromPoint(cx, cy);
                    if (curEl && !curEl[expando]) {
                        curEl[expando] = new Number(0);
                        elements.push(curEl);
                        cx += curEl.offsetWidth;
                    } else {
                        cx += 5;
                    }
                }
            }

            return elements;

        }

        console.log("Getting elements...:" + getElementsInRegion(x1, y1, x2 - x1, y2 - y1));
    }

}

chrome.runtime.onMessage.addListener(processRequest);
<commit_msg>#52 gokhan:Annotation JS basic integration without server connection<commit_after>function processRequest(request, sender, sendResponse) {
    preProcess();
    startAnnotation(request.data);
    chrome.runtime.onMessage.removeListener(processRequest);
}

function preProcess() {
    // while (document.body.firstChild) {
    //     document.body.firstChild.remove();
    // }
    var canvas = document.createElement("canvas");
    canvas.class = 'selectionBox';
    canvas.id = 'selectionBox';
    canvas.style = 'position: absolute; top: 0; left: 0; height: 0; width: 0; border: 1px solid red;';
    document.body.appendChild(canvas);
    // var selectDiv = document.createElement("div");
    // selectDiv.class = 'selectionBox';
    // selectDiv.style = 'position: absolute; top: 0; left: 0; height: 300; width: 300; border: 1px solid red;';
    // document.body.appendChild(selectDiv);
}

function startAnnotationDrawing() {
    if ($('#selectionBox').length) {
        alert("Please select an area to annotate");
    } else {
        alert("Something is wrong with annotation selector");
    }
    // var html = document.documentElement;
    // html.className += " annotateClass";

    var mouse_down = false;

    var start_pos_x = 0;
    var start_pos_y = 0;
    var end_pos_x = 0;
    var end_pos_y = 0;

    $(function () {
        $('html').mousedown(function (e) {
            mouse_down = true;
            start_pos_x = e.pageX;
            start_pos_y = e.pageY;
        });

        $('html').mousemove(function (e) {
            end_pos_x = e.pageX;
            end_pos_y = e.pageY;

            if (mouse_down) {
                draw(start_pos_x, start_pos_y, end_pos_x, end_pos_y);
            }
        });

        $('html').mouseup(function (e) {
            end_pos_x = e.pageX;
            end_pos_y = e.pageY;

            if (mouse_down) {
                draw(start_pos_x, start_pos_y, end_pos_x, end_pos_y);
            }

            mouse_down = false;

            get_elements(start_pos_x, start_pos_y, end_pos_x, end_pos_y);
        });
    });
}
function startAnnotatorJS() {
    var app = new annotator.App();
    app.include(annotator.ui.main);
    app.include(annotator.storage.http);
    app.start();
    if (app != null) {
        alert("Please select something and click on annotate Icon");
    } else {
        alert("Something is wrong with annotation selector");
    }
}
function startAnnotation(data) {

    if (!window.jQuery) {
        alert("JQ does NOT work");
    }
    startAnnotatorJS();

    //startAnnotationDrawing();

    function draw(x1, y1, x2, y2) {
        // console.log("Drawing top:" + x1 + ", left:" + x2 + ", width:" + (x2 - x1) + ", height:" + (y2 - y1));
        var canvas = document.getElementById('selectionBox');
        canvas.style = 'position: absolute; top: ' + y1 + 'px; left: ' + x1 + 'px; height: ' + (y2 - y1) + 'px; width: ' + (x2 - x1) + 'px; border: 1px solid blue;';
        // $('.selectionBox').css({
        //     'left': x1 + 'px',
        //     'top': y1 + 'px',
        //     'width': (x2 - x1) + 'px',
        //     'height': (y2 - y1) + 'px'
        // });
    }

    function get_elements(x1, y1, x2, y2) {
        // var element_list = '';
        //
        // $('#main *').each(function () {
        //     if (!($(this).attr('class') == 'selectionBox')) {
        //         var offset = $(this).offset();
        //
        //         var element_x1 = offset.left;
        //         var element_y1 = offset.top;
        //         var element_x2 = offset.left + $(this).width();
        //         var element_y2 = offset.top + $(this).height();
        //
        //         if (
        //             (
        //                 ((x1 >= element_x1 && x1 <= element_x2) && (y1 >= element_y1 && y1 <= element_y2)) ||
        //                 ((x2 >= element_x1 && x2 <= element_x2) && (y1 >= element_y1 && y1 <= element_y2)) ||
        //                 ((x2 >= element_x1 && x2 <= element_x2) && (y2 >= element_y1 && y2 <= element_y2)) ||
        //                 ((x1 >= element_x1 && x1 <= element_x2) && (y2 >= element_y1 && y2 <= element_y2))
        //             ) ||
        //             (
        //                 ((element_x1 >= x1 && element_x1 <= x2) && (element_y1 >= y1 && element_y1 <= y2)) ||
        //                 ((element_x2 >= x1 && element_x2 <= x2) && (element_y1 >= y1 && element_y1 <= y2)) ||
        //                 ((element_x2 >= x1 && element_x2 <= x2) && (element_y2 >= y1 && element_y2 <= y2)) ||
        //                 ((element_x1 >= x1 && element_x1 <= x2) && (element_y2 >= y1 && element_y2 <= y2))
        //             )
        //         ) {
        //             element_list += this.nodeName + ' -> ' + $(this).attr('class') + '
';
        //         }
        //     }
        // });
        //
        // $('.output').html(element_list);
        // return getElementsInRegion(x1,y1,x2-x1,y2-y1);
        function getElementsInRegion(x, y, width, height) {
            console.log("Selecting elements in region x,y:" + x + ", " + y + " , width:" + width + ", height:" + height);
            var elements = [],
                expando = +new Date,
                cx = x,
                cy = y,
                curEl;

            height = y + height;
            width = x + width;

            while ((cy += 5) < height) {
                cx = x;
                while (cx < width) {
                    curEl = document.elementFromPoint(cx, cy);
                    if (curEl && !curEl[expando]) {
                        curEl[expando] = new Number(0);
                        elements.push(curEl);
                        cx += curEl.offsetWidth;
                    } else {
                        cx += 5;
                    }
                }
            }

            return elements;

        }

        console.log("Getting elements...:" + getElementsInRegion(x1, y1, x2 - x1, y2 - y1));
    }

}

chrome.runtime.onMessage.addListener(processRequest);
<|endoftext|>


<commit_before>(function (App) {
  'use strict';

  var init = function () {
    // We can't use a Backbone router here because the domain and path of the sites are
    // chosen by a manager. In order to know which JS router/view to instantiate, we read
    // a global variable called "route" created inside the rails view matching each template

    var routerName = 'Front' + window.route;

    if (App.Router[routerName]) {
      // Because turbolinks doesn't fully reload the page, we need to stop the
      // history before anything else
      Backbone.history.stop();

      // Backbone.history.stop has some asynchronous events that can trigger twice
      // the same route when Backbone.history.start is executed
      setTimeout(function () {
        new App.Router[routerName]();
      }, 0);

      // NOTE: Don't forget to start Backbone.history in the router

      // This component is in charge of the translation selector
      new App.View.LanguageSelectorView();
      new App.View.LanguageSelectorView({ el: '.js-language-selector-mobile' });
    } else {
      // eslint-disable-next-line no-console
      console.warn('The route ' + window.route + ' doesn\'t have any associated router.');
    }
  };

  // We need for the DOM to be ready
  document.addEventListener('turbolinks:load', init);
}).call(this, this.App);
<commit_msg>listens to changes between language selectors to maintain them in sync<commit_after>(function (App) {
  'use strict';

  var init = function () {
    // We can't use a Backbone router here because the domain and path of the sites are
    // chosen by a manager. In order to know which JS router/view to instantiate, we read
    // a global variable called "route" created inside the rails view matching each template

    var routerName = 'Front' + window.route;

    if (App.Router[routerName]) {
      // Because turbolinks doesn't fully reload the page, we need to stop the
      // history before anything else
      Backbone.history.stop();

      // Backbone.history.stop has some asynchronous events that can trigger twice
      // the same route when Backbone.history.start is executed
      setTimeout(function () {
        new App.Router[routerName]();
      }, 0);

      // NOTE: Don't forget to start Backbone.history in the router

      // NOTE: because there's two language selectors in the webpage, we need to maintain them in sync
      var desktopLanguageSelector = new App.View.LanguageSelectorView();
      var mobileDesktopLanguageSelector = new App.View.LanguageSelectorView({ el: '.js-language-selector-mobile' });

      // Here we listen to changes in one selector and manually update the other one.
      desktopLanguageSelector.listenTo(mobileDesktopLanguageSelector, 'state:change', function (state) {
        this.updateCurrentLanguage(state.currentLanguage);
      });
      mobileDesktopLanguageSelector.listenTo(desktopLanguageSelector, 'state:change', function (state) {
        this.updateCurrentLanguage(state.currentLanguage);
      });
    } else {
      // eslint-disable-next-line no-console
      console.warn('The route ' + window.route + ' doesn\'t have any associated router.');
    }
  };

  // We need for the DOM to be ready
  document.addEventListener('turbolinks:load', init);
}).call(this, this.App);
<|endoftext|>


<commit_before>// File upload
// https://github.com/shrinerb/shrine/wiki/Adding-Direct-S3-Uploads#aws-s3-setup

(function() {
  var multiFileUploadUppy;

  var disableForm = function($form) {
    var $inputs = $form.find('input[type="submit"]');

    $inputs.prop('disabled', true);
  };

  var enableForm = function($form) {
    var $inputs = $form.find('input[type="submit"]');

    $inputs.prop('disabled', false);
  };

  var generateFileData = function(file, response) {
    return JSON.stringify({
             id: response.uploadURL.match(/\/cache\/([^\?]+)/)[1], // extract key without prefix
             storage: 'cache',
             metadata: {
               size:      file.size,
               filename:  file.name,
               mime_type: file.type,
             }
           });
  };

  var generateFileDataForAjaxPost = function(file, response) {
    return {
             attachment: generateFileData(file, response)
           };
  };

  var createMediaItemFromUploadedFileData = function($fileUpload, uploadedFileData, uppy) {
    var url = $fileUpload.attr('data-media-item-url');
    var $mediaLibary = $('#media-library-infinite-load');

    $.ajax({
      method: 'POST',
      url: url,
      dataType: 'json',
      data: {
        media_item: uploadedFileData
      }
    })
    .done(function(data) {
      $mediaLibary.prepend(data['attachmentPartial']);
    })
    .fail(function(data) {
      console.warn('Media item failed to create', data);
      uppy.info( ('Error uploading file: ' + data), 'error' );
    });
  };

  var singleFileUpload = function($fileUpload) {
    var $form = $fileUpload.closest('form');
    var $wrapper = $fileUpload.closest('.file-upload-wrapper');
    var hiddenInput = $fileUpload.find('.file-upload__data')[0];
    var imagePreview = document.querySelector('.upload-preview img');
    var fileInput = $fileUpload.find('.file-upload__file')[0];
    var formGroup = $fileUpload[0];
    var informerParent = $wrapper.find('.file-upload-notifications');

    // remove our file input in favour of Uppy's
    formGroup.removeChild(fileInput)

    var uppy = Uppy.Core({
        autoProceed: true
      })
      .use(Uppy.FileInput, {
        target: formGroup,
        locale: {
          strings: {
            chooseFiles: 'Choose file'
          }
        }
      })
      .use(Uppy.Informer, {
        target: informerParent[0],
      })
      .use(Uppy.StatusBar, {
        target: $fileUpload[0]
      })
      .use(Uppy.ThumbnailGenerator, {
        thumbnailWidth: ($fileUpload.width() * 2),
      })
      uppy.use(Uppy.AwsS3Multipart, {
        companionUrl: '/',
      });

    uppy.on('thumbnail:generated', function(file, preview) {
      // show preview of the image using URL from thumbnail generator
      imagePreview.src = preview
    });

    uppy.on('upload', function(file, response) {
      disableForm($form);
    });

    uppy.on('upload-success', function(file, response) {
      // construct uploaded file data in the format that Shrine expects
      var uploadedFileData = generateFileData(file, response);

      uppy.info('File uploaded. Press the Update Media item button to save the record.', 'success', 600000);

      // set hidden field value to the uploaded file data so that it's submitted
      // with the form as the attachment
      hiddenInput.value = uploadedFileData;

      enableForm($form);
    });
  };

  var initializeUppyDashboardModal = function(uppy, $fileUpload) {
    $(document).on('dragenter.uppyDashboardModal', function(e) {
      $(document).off('dragenter.uppyDashboardModal');
      uppy.getPlugin('Dashboard').openModal();
      e.preventDefault();
    });
  };

  var multiFileUpload = function($fileUpload) {
    var uppy = Uppy.Core({
        autoProceed: true,
      })
      .use(Uppy.Dashboard, {
        inline: false,
        proudlyDisplayPoweredByUppy: false,
        closeModalOnClickOutside: true,
        showLinkToFileUploadResult: false,
        // height: 300,
        // width: '100%',
        // hideProgressAfterFinish: true
      })
      .use(Uppy.ThumbnailGenerator, {
        thumbnailWidth: 600,
      })
      uppy.use(Uppy.AwsS3Multipart, {
        companionUrl: '/',
      });

    multiFileUploadUppy = uppy;

    initializeUppyDashboardModal(uppy, $fileUpload);

    uppy.on('dashboard:modal-closed', function() {
      initializeUppyDashboardModal(uppy, $fileUpload);
    });

    uppy.on('upload-success', function(file, response) {
      // construct uploaded file data in the format that Shrine expects
      var uploadedFileData = generateFileDataForAjaxPost(file, response);

      createMediaItemFromUploadedFileData($fileUpload, uploadedFileData, uppy);
    });
  };

  var initializeMultiFileUpload = function($multiFileUpload) {
    if ( $multiFileUpload.length ) {
      multiFileUpload( $multiFileUpload );
    }
  };

  var destroyMultiFileUpload = function($multiFileUpload) {
    if ( multiFileUploadUppy ) multiFileUploadUppy.close();
    $(document).off('dragenter.uppyDashboardModal');
  };

  App.pageLoad.push(function() {
    $('.file-upload').each(function() {
      singleFileUpload( $(this) );
    });

    initializeMultiFileUpload( $('.multi-file-upload').filter(':visible') );
  });

  $(document).on('show.bs.modal', function(e) {
    var $modal = $(e.target);

    if ( $modal.attr('id') == 'media-item-chooser' ) {
      initializeMultiFileUpload( $('#media-item-chooser .multi-file-upload') );
    }
  });

  $(document).on('hide.bs.modal', function(e) {
    var $modal = $(e.target);

    if ( $modal.attr('id') == 'media-item-chooser' ) {
      destroyMultiFileUpload( $('#media-item-chooser .multi-file-upload') );
    }
  });
})();
<commit_msg>Close and reset uppy dashboard after finish<commit_after>// File upload
// https://github.com/shrinerb/shrine/wiki/Adding-Direct-S3-Uploads#aws-s3-setup

(function() {
  var multiFileUploadUppy;

  var disableForm = function($form) {
    var $inputs = $form.find('input[type="submit"]');

    $inputs.prop('disabled', true);
  };

  var enableForm = function($form) {
    var $inputs = $form.find('input[type="submit"]');

    $inputs.prop('disabled', false);
  };

  var generateFileData = function(file, response) {
    return JSON.stringify({
             id: response.uploadURL.match(/\/cache\/([^\?]+)/)[1], // extract key without prefix
             storage: 'cache',
             metadata: {
               size:      file.size,
               filename:  file.name,
               mime_type: file.type,
             }
           });
  };

  var generateFileDataForAjaxPost = function(file, response) {
    return {
             attachment: generateFileData(file, response)
           };
  };

  var createMediaItemFromUploadedFileData = function($fileUpload, uploadedFileData, uppy) {
    var url = $fileUpload.attr('data-media-item-url');
    var $mediaLibary = $('#media-library-infinite-load');

    $.ajax({
      method: 'POST',
      url: url,
      dataType: 'json',
      data: {
        media_item: uploadedFileData
      }
    })
    .done(function(data) {
      $mediaLibary.prepend(data['attachmentPartial']);
    })
    .fail(function(data) {
      console.warn('Media item failed to create', data);
      uppy.info( ('Error uploading file: ' + data), 'error' );
    });
  };

  var singleFileUpload = function($fileUpload) {
    var $form = $fileUpload.closest('form');
    var $wrapper = $fileUpload.closest('.file-upload-wrapper');
    var hiddenInput = $fileUpload.find('.file-upload__data')[0];
    var imagePreview = document.querySelector('.upload-preview img');
    var fileInput = $fileUpload.find('.file-upload__file')[0];
    var formGroup = $fileUpload[0];
    var informerParent = $wrapper.find('.file-upload-notifications');

    // remove our file input in favour of Uppy's
    formGroup.removeChild(fileInput)

    var uppy = Uppy.Core({
        autoProceed: true
      })
      .use(Uppy.FileInput, {
        target: formGroup,
        locale: {
          strings: {
            chooseFiles: 'Choose file'
          }
        }
      })
      .use(Uppy.Informer, {
        target: informerParent[0],
      })
      .use(Uppy.StatusBar, {
        target: $fileUpload[0]
      })
      .use(Uppy.ThumbnailGenerator, {
        thumbnailWidth: ($fileUpload.width() * 2),
      })
      uppy.use(Uppy.AwsS3Multipart, {
        companionUrl: '/',
      });

    uppy.on('thumbnail:generated', function(file, preview) {
      // show preview of the image using URL from thumbnail generator
      imagePreview.src = preview
    });

    uppy.on('upload', function(file, response) {
      disableForm($form);
    });

    uppy.on('upload-success', function(file, response) {
      // construct uploaded file data in the format that Shrine expects
      var uploadedFileData = generateFileData(file, response);

      uppy.info('File uploaded. Press the Update Media item button to save the record.', 'success', 600000);

      // set hidden field value to the uploaded file data so that it's submitted
      // with the form as the attachment
      hiddenInput.value = uploadedFileData;

      enableForm($form);
    });
  };

  var initializeUppyDashboardModal = function(uppy, $fileUpload) {
    uppy.reset();

    $(document).on('dragenter.uppyDashboardModal', function(e) {
      $(document).off('dragenter.uppyDashboardModal');
      uppy.getPlugin('Dashboard').openModal();
      e.preventDefault();
    });
  };

  var multiFileUpload = function($fileUpload) {
    var uppy = Uppy.Core({
        autoProceed: true
      })
      .use(Uppy.Dashboard, {
        inline: false,
        proudlyDisplayPoweredByUppy: false,
        closeModalOnClickOutside: true,
        showLinkToFileUploadResult: false,
        closeAfterFinish: true
        // height: 300,
        // width: '100%',
        // hideProgressAfterFinish: true
      })
      .use(Uppy.ThumbnailGenerator, {
        thumbnailWidth: 600,
      })
      uppy.use(Uppy.AwsS3Multipart, {
        companionUrl: '/',
      });

    multiFileUploadUppy = uppy;

    initializeUppyDashboardModal(uppy, $fileUpload);

    uppy.on('dashboard:modal-closed', function() {
      initializeUppyDashboardModal(uppy, $fileUpload);
    });

    uppy.on('upload-success', function(file, response) {
      // construct uploaded file data in the format that Shrine expects
      var uploadedFileData = generateFileDataForAjaxPost(file, response);

      createMediaItemFromUploadedFileData($fileUpload, uploadedFileData, uppy);
    });
  };

  var initializeMultiFileUpload = function($multiFileUpload) {
    if ( $multiFileUpload.length ) {
      multiFileUpload( $multiFileUpload );
    }
  };

  var destroyMultiFileUpload = function($multiFileUpload) {
    if ( multiFileUploadUppy ) multiFileUploadUppy.close();
    $(document).off('dragenter.uppyDashboardModal');
  };

  App.pageLoad.push(function() {
    $('.file-upload').each(function() {
      singleFileUpload( $(this) );
    });

    initializeMultiFileUpload( $('.multi-file-upload').filter(':visible') );
  });

  $(document).on('show.bs.modal', function(e) {
    var $modal = $(e.target);

    if ( $modal.attr('id') == 'media-item-chooser' ) {
      initializeMultiFileUpload( $('#media-item-chooser .multi-file-upload') );
    }
  });

  $(document).on('hide.bs.modal', function(e) {
    var $modal = $(e.target);

    if ( $modal.attr('id') == 'media-item-chooser' ) {
      destroyMultiFileUpload( $('#media-item-chooser .multi-file-upload') );
    }
  });
})();
<|endoftext|>


<commit_before>// @flow

import React from "react";
import PropTypes from 'prop-types';
import { createFragmentContainer, graphql } from "react-relay/compat";

import Button from "../../shared/Button";

import GraphQLExplorerConsoleEditor from "./GraphQLExplorerConsoleEditor";
import GraphQLExplorerConsoleResultsViewer from "./GraphQLExplorerConsoleResultsViewer";

import { getCurrentQuery, setCurrentQuery, interpolateQuery } from "./query";
import { getCachedResults, setCachedResults } from "./results";
import { executeGraphQLQuery } from "./network";

import { DEFAULT_QUERY_WITH_ORGANIZATION, DEFAULT_QUERY_NO_ORGANIZATION } from "./defaults";

type OrganizationEdge = {
  node: {
    id: string,
    name: string,
    slug: string
  }
};

type Props = {
  viewer: {
    organizations: {
      edges: Array<OrganizationEdge>
    }
  }
};

type State = {
  performance: string,
  results: string,
  executing: boolean,
  executeCurrentQuery: boolean
};

class GraphQLExplorerConsole extends React.PureComponent<Props, State> {
  state = {
    performance: null,
    results: null,
    executing: false,
    executedFirstQuery: false
  };

  static contextTypes = {
    router: PropTypes.object.isRequired
  }

  constructor(props) {
    super(props);

    // Let the component know that we've already executed a query and we'll
    // just be showing that instead.
    const cachedResults = getCachedResults();
    if (cachedResults) {
      this.state = {
        executedFirstQuery: true,
        results: cachedResults.results,
        performance: cachedResults.performance
      };
    }
  }

  executeCurrentQuery() {
    this.setState({ executing: true });

    executeGraphQLQuery({ query: this.getCurrentQuery() }).then((response) => {
      // Once we've got the resposne back, and converted it JSON
      response.json().then((json) => {
        // Now that we've got back some real JSON, let's turn it back into a
        // string... The things we do to make it look pretty! (The 2 means
        // indent each nested object with 2 spaces)
        const prettyJSONString = JSON.stringify(json, null, 2);

        // Get performance information out of the query if there is any.
        const responsePerformanceInformation = response.headers.get('x-buildkite-performance');

        // Also store the pretty JSON in the results cache so next time we
        // re-render the component we can show the previous results. Makes for
        // great tab switching!
        setCachedResults(prettyJSONString, responsePerformanceInformation);

        // Tell the console we're not executing anymore, and that it can stop
        // showing a spinner.
        this.setState({
          results: prettyJSONString,
          performance: responsePerformanceInformation,
          executing: false,
          executedFirstQuery: true
        });
      });
    });
  }

  getCurrentQuery() {
    let query = getCurrentQuery();

    // If there isn't a query currently in local storage, let's make up one
    // based on one of the examples.
    if (!query) {
      // If we've got an organization loaded, let's use the default query that
      // looks at the first organization. If the user isn't part of any
      // organization, we'll use the default that doesn't retrieve organization
      // information.
      if (this.props.viewer.organizations.edges.length) {
        query = interpolateQuery(DEFAULT_QUERY_WITH_ORGANIZATION, {
          organization: this.props.viewer.organizations.edges[0].node
        });
      } else {
        query = DEFAULT_QUERY_NO_ORGANIZATION;
      }
    }

    return query;
  }

  render() {
    return (

          <Button onClick={this.handleExecuteClick} loading={this.state.executing && "Executing…"}>Execute</Button>

            <GraphQLExplorerConsoleEditor value={this.getCurrentQuery()} onChange={this.handleEditorChange} />

              {this.renderOutputPanel()}

    );
  }

  renderOutputPanel() {
    if (!this.state.executedFirstQuery) {
      return (

          Hit the Execute above button to run this query! ☝

      );
    }
    return (
      <React.Fragment>
        <GraphQLExplorerConsoleResultsViewer results={this.state.results} className="p1 flex-auto" style={{ width: "100%" }} />
        {this.renderDebuggingInformation()}
      </React.Fragment>
    );

  }

  renderDebuggingInformation() {
    // Only render debugging information if we've got some to show, and we're
    // in "debug" mode.
    if (this.state.performance && this.context.router.location.query["debug"] === "true") {
      return (

Performance 🚀

{this.state.performance.split("; ").join("\n")}

      );
    }
  }

  handleExecuteClick = () => {
    event.preventDefault();
    this.executeCurrentQuery();
  };

  handleEditorChange = (value) => {
    setCurrentQuery(value);
  };
}

export default createFragmentContainer(GraphQLExplorerConsole, {
  viewer: graphql`
    fragment GraphQLExplorerConsole_viewer on Viewer {
      organizations(first: 100) {
        edges {
          node {
            id
            name
            slug
          }
        }
      }
    }
`
});
<commit_msg>Fixed some flowtype defs<commit_after>// @flow

import React from "react";
import PropTypes from 'prop-types';
import { createFragmentContainer, graphql } from "react-relay/compat";

import Button from "../../shared/Button";

import GraphQLExplorerConsoleEditor from "./GraphQLExplorerConsoleEditor";
import GraphQLExplorerConsoleResultsViewer from "./GraphQLExplorerConsoleResultsViewer";

import { getCurrentQuery, setCurrentQuery, interpolateQuery } from "./query";
import { getCachedResults, setCachedResults } from "./results";
import { executeGraphQLQuery } from "./network";

import { DEFAULT_QUERY_WITH_ORGANIZATION, DEFAULT_QUERY_NO_ORGANIZATION } from "./defaults";

type OrganizationEdge = {
  node: {
    id: string,
    name: string,
    slug: string
  }
};

type Props = {
  viewer: {
    organizations: {
      edges: Array<OrganizationEdge>
    }
  }
};

type State = {
  performance?: string,
  results?: string,
  executing: boolean,
  executedFirstQuery: boolean
};

class GraphQLExplorerConsole extends React.PureComponent<Props, State> {
  state = {
    executing: false,
    executedFirstQuery: false
  };

  static contextTypes = {
    router: PropTypes.object.isRequired
  }

  constructor(props) {
    super(props);

    // Let the component know that we've already executed a query and we'll
    // just be showing that instead.
    const cachedResults = getCachedResults();
    if (cachedResults) {
      this.state = {
        performance: cachedResults.performance,
        results: cachedResults.results,
        executing: false,
        executedFirstQuery: true
      };
    }
  }

  executeCurrentQuery() {
    this.setState({ executing: true });

    executeGraphQLQuery({ query: this.getCurrentQuery() }).then((response) => {
      // Once we've got the resposne back, and converted it JSON
      response.json().then((json) => {
        // Now that we've got back some real JSON, let's turn it back into a
        // string... The things we do to make it look pretty! (The 2 means
        // indent each nested object with 2 spaces)
        const prettyJSONString = JSON.stringify(json, null, 2);

        // Get performance information out of the query if there is any.
        const responsePerformanceInformation = response.headers.get('x-buildkite-performance');

        // Also store the pretty JSON in the results cache so next time we
        // re-render the component we can show the previous results. Makes for
        // great tab switching!
        setCachedResults(prettyJSONString, responsePerformanceInformation);

        // Tell the console we're not executing anymore, and that it can stop
        // showing a spinner.
        this.setState({
          results: prettyJSONString,
          performance: responsePerformanceInformation,
          executing: false,
          executedFirstQuery: true
        });
      });
    });
  }

  getCurrentQuery() {
    let query = getCurrentQuery();

    // If there isn't a query currently in local storage, let's make up one
    // based on one of the examples.
    if (!query) {
      // If we've got an organization loaded, let's use the default query that
      // looks at the first organization. If the user isn't part of any
      // organization, we'll use the default that doesn't retrieve organization
      // information.
      if (this.props.viewer.organizations.edges.length) {
        query = interpolateQuery(DEFAULT_QUERY_WITH_ORGANIZATION, {
          organization: this.props.viewer.organizations.edges[0].node
        });
      } else {
        query = DEFAULT_QUERY_NO_ORGANIZATION;
      }
    }

    return query;
  }

  render() {
    return (

          <Button onClick={this.handleExecuteClick} loading={this.state.executing && "Executing…"}>Execute</Button>

            <GraphQLExplorerConsoleEditor value={this.getCurrentQuery()} onChange={this.handleEditorChange} />

              {this.renderOutputPanel()}

    );
  }

  renderOutputPanel() {
    if (!this.state.executedFirstQuery) {
      return (

          Hit the Execute above button to run this query! ☝

      );
    }
    return (
      <React.Fragment>
        <GraphQLExplorerConsoleResultsViewer results={this.state.results} className="p1 flex-auto" style={{ width: "100%" }} />
        {this.renderDebuggingInformation()}
      </React.Fragment>
    );

  }

  renderDebuggingInformation() {
    // Only render debugging information if we've got some to show, and we're
    // in "debug" mode.
    if (this.state.performance && this.context.router.location.query["debug"] === "true") {
      return (

Performance 🚀

{this.state.performance.split("; ").join("\n")}

      );
    }
  }

  handleExecuteClick = () => {
    event.preventDefault();
    this.executeCurrentQuery();
  };

  handleEditorChange = (value) => {
    setCurrentQuery(value);
  };
}

export default createFragmentContainer(GraphQLExplorerConsole, {
  viewer: graphql`
    fragment GraphQLExplorerConsole_viewer on Viewer {
      organizations(first: 100) {
        edges {
          node {
            id
            name
            slug
          }
        }
      }
    }
`
});
<|endoftext|>


<commit_before>
import React, {Component} from "react"
import Button, { ButtonGroup } from '@atlaskit/button';
//import RadioGroup, { AkFieldRadioGroup, AkRadio } from '@atlaskit/field-radio-group';
import FieldRadioGroup from '@atlaskit/field-radio-group';
import Modal from '@atlaskit/modal-dialog';
import DropdownMenu, {
  DropdownItemGroup,
  DropdownItem,
} from '@atlaskit/dropdown-menu';

import InlineDialog from '@atlaskit/inline-dialog';
import {parseJwt, generateJWT} from './jwt'

// same as SegmentItemButton
export class SegmentItemButton extends Component {
  state = {
    dialogOpen: this.props.open,
    selectedOption: this.props.predicate.comparison
  };

  onRadioChange = (e)=> {
    this.setState({
      selectedOption: e.target.value
    })
  };

  handleSubmit = (e)=> {
    //this.props.predicate.type
    let value = null
    switch(this.props.predicate.type){
      case "string": {
        value = `${this.refs.relative_input.value}`
        break;
      }
      case "date": {
        value = `${this.refs.relative_input.value} days ago`
        break;
      }
    }

    const h = {
      comparison: this.state.selectedOption.replace("relative:", ""),
      value: value
    }

    const response = Object.assign({}, this.props.predicate, h )
    this.props.updatePredicate(response, this.props.predicateCallback )
  }

  handleDelete = (e) => {
    this.props.deletePredicate(this.props.predicate, this.props.predicateCallback)
     // /apps/:app_id/segments/:id/delete_predicate
  }

  renderOptions = () => {

    switch(this.props.predicate.type){
      case "string": {
        return this.contentString()
      }

      case "date": {
        return this.contentDate()
      }
    }

  }

  contentString = () => {

    const compare = (value)=>{
      return this.props.predicate.comparison === value
    }

    const relative = [
      {label: "is", value: "eq", defaultSelected: false},
      {label: "is not", value: "not_eq", defaultSelected: false},
      {label: "starts with", value: "contains_start", defaultSelected: false},
      {label: "ends with", value: "contains_ends", defaultSelected: false},
      {label: "contains", value: "contains", defaultSelected: false},
      {label: "does not contain", value: "not_contains", defaultSelected: false},
      {label: "is unknown", value: "is_null", defaultSelected: false},
      {label: "has any value", value: "is_not_null", defaultSelected: false},
    ]

    return

Update String

Select the filter

              <FieldRadioGroup
                items={relative}
                label="Relative:"
                onRadioChange={this.onRadioChange.bind(this)}
              />

              { this.state.selectedOption &&
                (this.state.selectedOption !== "is_null" ||
                  this.state.selectedOption !== "is_not_null") ?

                  <input
                    defaultValue={null}
                    type="text"
                    ref={"relative_input"}
                  />

                  <Button appearance="link"
                    onClick={this.handleSubmit.bind(this)}>
                    save changes
                  </Button>

 : null
              }

              { !this.props.predicate.comparison ? null : this.deleteButton() }

  }

  contentDate = () => {

    const compare = (value)=>{
      return this.props.predicate.comparison === value
    }

    const relative = [
      {label: "more than", value: "lt", defaultSelected: compare("lt")  },
      {label: "exactly", value: "eq",  defaultSelected: compare("eq")  },
      {label: "less than", value: "gt", defaultSelected: compare("gt")  },
    ]
    const absolute = [
      {name: "after", value: "absolute:gt"},
      {name: "on", value: "absolute:eq"},
      {name: "before", value: "absolute:lt"},
      {name: "is unknown", value: "absolute:eq"},
      {name: "has any value", value: "absolute:not_eq"},
    ]

    return

Update date

Select the filter

              <FieldRadioGroup
                items={relative}
                label="Relative:"
                onRadioChange={this.onRadioChange.bind(this)}
              />

              { this.state.selectedOption ?

                  <input
                    defaultValue={30}
                    type="number"
                    ref={"relative_input"}/>
                  days ago

                  <Button appearance="link"
                    onClick={this.handleSubmit.bind(this)}>
                    save changes
                  </Button>

 : null
              }

              { !this.props.predicate.comparison ? null : this.deleteButton() }

  }

  deleteButton = () => {
    return <Button appearance="link"
            onClick={this.handleDelete.bind(this)}>
            Delete
           </Button>
  }

  toggleDialog = (e) => this.setState({ dialogOpen: !this.state.dialogOpen });

  render() {
    return (

        <InlineDialog content={this.renderOptions()}
                      isOpen={this.state.dialogOpen}
                      position={"bottom left"}
                      shouldFlipunion={true}>

          {
            !this.props.predicate.comparison ?

              <Button isLoading={false}
                appearance={this.state.dialogOpen ? 'default' : 'danger'}
                onClick={this.toggleDialog}>
                {
                  !this.state.dialogOpen ?
                  "Missing value!" :
                  this.props.text
                }
              </Button> :

              <Button isLoading={false}
                appearance={this.props.appearance}
                onClick={this.toggleDialog}>
                {this.props.text}
              </Button>
          }

        </InlineDialog>

    );
  }
}

export class SaveSegmentModal extends Component {
  state: State = {
    isOpen: false,
    action: "update",
    loading: false,
    input: null
  };
  open  = () => this.setState({ isOpen: true });
  close = () => this.setState({ isOpen: false });

  secondaryAction = ({ target }: Object) => {
    this.props.savePredicates({
      action: this.state.action,
      input: this.refs.input ? this.refs.input.value : null
    }, ()=> {
      this.close()
      if(this.props.predicateCallback)
        this.props.predicateCallback()
    })
  }

  deleteAction = ({ target }: Object) => {
    this.props.deleteSegment(this.props.segment.id, this.close )
  }

  handleChange = ({target})=> {
    this.setState({
      action: target.value,
    })
  }

  render() {
    const { isOpen, loading } = this.state;
    const actions = [
      { text: 'Close', onClick: this.close },
      { text: 'Save Segment', onClick: this.secondaryAction.bind(this) },
      { text: 'Remove Segment', onClick: this.deleteAction.bind(this) }
    ];

    return (

        <Button isLoading={false}
          appearance={'link'}
          onClick={this.open}>

          {" "}
          Save Segment
        </Button>

        <Button isLoading={false}
          appearance={'link danger'}
          onClick={this.deleteAction.bind(this)}>

          {" "}
          remove Segment
        </Button>

        {isOpen && (
          <Modal actions={actions}
            onClose={this.close}
            heading={this.props.title}>

            {
              !loading ?

                  <FieldRadioGroup
                    items={
                      [
                        {label: `Save changes to the segment ‘${this.props.segment.name}’`, value: "update", defaultSelected: true  },
                        {label: "Create new segment", value: "new" },
                      ]
                    }
                    label="options:"
                    onRadioChange={this.handleChange.bind(this)}
                  />

                  {
                    this.state.action === "new" ?
                    <input name="name" ref="input"/> : null
                  }

 : <Spinner/>
            }

          </Modal>
        )}

    );
  }
}

export class InlineFilterDialog extends Component {
  state = {
    dialogOpen: false,
  };

  toggleDialog = (e) => this.setState({ dialogOpen: !this.state.dialogOpen });

  handleClick = (e, o) => {
    this.props.actions.addPredicate(o, this.props.handleClick)
  }

  render() {

    const fields = [
      {name: "last_visited_at", type: "string"},
      {name: "referrer", type: "string"},
      {name: "state", type: "string"},
      {name: "ip", type: "string"},
      {name: "city", type: "string"},
      {name: "region", type: "string"},
      {name: "country", type: "string"},
      {name: "lat", type: "string"},
      {name: "lng", type: "string"},
      {name: "postal", type: "string"},
      {name: "web_sessions", type: "string"},
      {name: "timezone", type: "string"},
      {name: "browser", type: "string"},
      {name: "browser_version", type: "string"},
      {name: "os", type: "string"},
      {name: "os_version", type: "string"},
      {name: "browser_language", type: "string"},
      {name: "lang", type: "string"},
    ]

    const content = (

Select field

oeoe

          {
            fields.map((o)=>

                              <Button onClick={(e)=> this.handleClick.bind(this)(e, o)}>
                                {o.name}
                              </Button>

            )
          }

    );

    return (

        <InlineDialog
          content={content}
          isOpen={this.state.dialogOpen}
          position="bottom left">

          <Button isLoading={false}
            appearance={'link'}
            onClick={this.toggleDialog}>

            {" "}
            Add filter
          </Button>
        </InlineDialog>

    );
  }
}

export default class SegmentManager extends Component {

  constructor(props){
    super(props)
  }

  handleClickOnSelectedFilter = (jwtToken)=>{
    const url = `/apps/${this.props.store.app.key}/segments/${this.props.store.segment.id}/${jwtToken}`
    //this.props.history.push(url)
  }

  render(){
    return

            <ButtonGroup>
              {
                this.props.actions.getPredicates().map((o, i)=>{
                    return <SegmentItemButton
                            key={i}
                            predicate={o}
                            open={ !o.comparison }
                            appearance={ o.comparison ? "primary" : "default"}
                            text={`Match: ${o.attribute} ${o.comparison ? o.comparison : '' } ${o.value ? o.value : ''}`}
                            updatePredicate={this.props.actions.updatePredicate}
                            deletePredicate={this.props.actions.deletePredicate}
                           />
                })
              }

              <InlineFilterDialog
                {...this.props}
                handleClick={this.handleClickOnSelectedFilter.bind(this)}
              />

              <SaveSegmentModal
                title="Save Segment"
                segment={this.props.store.segment}
                savePredicates={this.props.actions.savePredicates}
                deleteSegment={this.props.actions.deleteSegment}
              />

            </ButtonGroup>

              <ButtonGroup>

                {this.children}

              </ButtonGroup>

            Users {this.props.store.meta['total_count']}

  }
} <commit_msg>render segments on campaign<commit_after>
import React, {Component} from "react"
import Button, { ButtonGroup } from '@atlaskit/button';
//import RadioGroup, { AkFieldRadioGroup, AkRadio } from '@atlaskit/field-radio-group';
import FieldRadioGroup from '@atlaskit/field-radio-group';
import Modal from '@atlaskit/modal-dialog';
import DropdownMenu, {
  DropdownItemGroup,
  DropdownItem,
} from '@atlaskit/dropdown-menu';

import InlineDialog from '@atlaskit/inline-dialog';
import {parseJwt, generateJWT} from './jwt'

// same as SegmentItemButton
export class SegmentItemButton extends Component {
  state = {
    dialogOpen: this.props.open,
    selectedOption: this.props.predicate.comparison
  };

  onRadioChange = (e)=> {
    this.setState({
      selectedOption: e.target.value
    })
  };

  handleSubmit = (e)=> {
    //this.props.predicate.type
    let value = null
    switch(this.props.predicate.type){
      case "string": {
        value = `${this.refs.relative_input.value}`
        break;
      }
      case "date": {
        value = `${this.refs.relative_input.value} days ago`
        break;
      }
    }

    const h = {
      comparison: this.state.selectedOption.replace("relative:", ""),
      value: value
    }

    const response = Object.assign({}, this.props.predicate, h )
    this.props.updatePredicate(response, this.props.predicateCallback )
  }

  handleDelete = (e) => {
    this.props.deletePredicate(this.props.predicate, this.props.predicateCallback)
     // /apps/:app_id/segments/:id/delete_predicate
  }

  renderOptions = () => {

    switch(this.props.predicate.type){
      case "string": {
        return this.contentString()
      }

      case "date": {
        return this.contentDate()
      }
    }

  }

  contentString = () => {

    const compare = (value)=>{
      return this.props.predicate.comparison === value
    }

    const relative = [
      {label: "is", value: "eq", defaultSelected: false},
      {label: "is not", value: "not_eq", defaultSelected: false},
      {label: "starts with", value: "contains_start", defaultSelected: false},
      {label: "ends with", value: "contains_ends", defaultSelected: false},
      {label: "contains", value: "contains", defaultSelected: false},
      {label: "does not contain", value: "not_contains", defaultSelected: false},
      {label: "is unknown", value: "is_null", defaultSelected: false},
      {label: "has any value", value: "is_not_null", defaultSelected: false},
    ]

    return

Update String

Select the filter

              <FieldRadioGroup
                items={relative}
                label="Relative:"
                onRadioChange={this.onRadioChange.bind(this)}
              />

              { this.state.selectedOption &&
                (this.state.selectedOption !== "is_null" ||
                  this.state.selectedOption !== "is_not_null") ?

                  <input
                    defaultValue={null}
                    type="text"
                    ref={"relative_input"}
                  />

                  <Button appearance="link"
                    onClick={this.handleSubmit.bind(this)}>
                    save changes
                  </Button>

 : null
              }

              { !this.props.predicate.comparison ? null : this.deleteButton() }

  }

  contentDate = () => {

    const compare = (value)=>{
      return this.props.predicate.comparison === value
    }

    const relative = [
      {label: "more than", value: "lt", defaultSelected: compare("lt")  },
      {label: "exactly", value: "eq",  defaultSelected: compare("eq")  },
      {label: "less than", value: "gt", defaultSelected: compare("gt")  },
    ]
    const absolute = [
      {name: "after", value: "absolute:gt"},
      {name: "on", value: "absolute:eq"},
      {name: "before", value: "absolute:lt"},
      {name: "is unknown", value: "absolute:eq"},
      {name: "has any value", value: "absolute:not_eq"},
    ]

    return

Update date

Select the filter

              <FieldRadioGroup
                items={relative}
                label="Relative:"
                onRadioChange={this.onRadioChange.bind(this)}
              />

              { this.state.selectedOption ?

                  <input
                    defaultValue={30}
                    type="number"
                    ref={"relative_input"}/>
                  days ago

                  <Button appearance="link"
                    onClick={this.handleSubmit.bind(this)}>
                    save changes
                  </Button>

 : null
              }

              { !this.props.predicate.comparison ? null : this.deleteButton() }

  }

  deleteButton = () => {
    return <Button appearance="link"
            onClick={this.handleDelete.bind(this)}>
            Delete
           </Button>
  }

  toggleDialog = (e) => this.setState({ dialogOpen: !this.state.dialogOpen });

  render() {
    return (

        <InlineDialog content={this.renderOptions()}
                      isOpen={this.state.dialogOpen}
                      position={"bottom left"}
                      shouldFlipunion={true}>

          {
            !this.props.predicate.comparison ?

              <Button isLoading={false}
                appearance={this.state.dialogOpen ? 'default' : 'danger'}
                onClick={this.toggleDialog}>
                {
                  !this.state.dialogOpen ?
                  "Missing value!" :
                  this.props.text
                }
              </Button> :

              <Button isLoading={false}
                appearance={this.props.appearance}
                onClick={this.toggleDialog}>
                {this.props.text}
              </Button>
          }

        </InlineDialog>

    );
  }
}

export class SaveSegmentModal extends Component {
  state: State = {
    isOpen: false,
    action: "update",
    loading: false,
    input: null
  };
  open  = () => this.setState({ isOpen: true });
  close = () => this.setState({ isOpen: false });

  secondaryAction = ({ target }: Object) => {
    this.props.savePredicates({
      action: this.state.action,
      input: this.refs.input ? this.refs.input.value : null
    }, ()=> {
      this.close()
      if(this.props.predicateCallback)
        this.props.predicateCallback()
    })
  }

  deleteAction = ({ target }: Object) => {
    this.props.deleteSegment(this.props.segment.id, this.close )
  }

  handleChange = ({target})=> {
    this.setState({
      action: target.value,
    })
  }

  render() {
    const { isOpen, loading } = this.state;
    const actions = [
      { text: 'Close', onClick: this.close },
      { text: 'Save Segment', onClick: this.secondaryAction.bind(this) },
      { text: 'Remove Segment', onClick: this.deleteAction.bind(this) }
    ];

    return (

        <Button isLoading={false}
          appearance={'link'}
          onClick={this.open}>

          {" "}
          Save Segment
        </Button>

        <Button isLoading={false}
          appearance={'link danger'}
          onClick={this.deleteAction.bind(this)}>

          {" "}
          remove Segment
        </Button>

        {isOpen && (
          <Modal actions={actions}
            onClose={this.close}
            heading={this.props.title}>

            {
              !loading ?

                  <FieldRadioGroup
                    items={
                      [
                        {label: `Save changes to the segment ‘${this.props.segment.name}’`, value: "update", defaultSelected: true  },
                        {label: "Create new segment", value: "new" },
                      ]
                    }
                    label="options:"
                    onRadioChange={this.handleChange.bind(this)}
                  />

                  {
                    this.state.action === "new" ?
                    <input name="name" ref="input"/> : null
                  }

 : <Spinner/>
            }

          </Modal>
        )}

    );
  }
}

export class InlineFilterDialog extends Component {
  state = {
    dialogOpen: false,
  };

  toggleDialog = (e) => this.setState({ dialogOpen: !this.state.dialogOpen });

  handleClick = (e, o) => {
    this.props.actions.addPredicate(o, this.props.handleClick)
  }

  render() {

    const fields = [
      {name: "last_visited_at", type: "string"},
      {name: "referrer", type: "string"},
      {name: "state", type: "string"},
      {name: "ip", type: "string"},
      {name: "city", type: "string"},
      {name: "region", type: "string"},
      {name: "country", type: "string"},
      {name: "lat", type: "string"},
      {name: "lng", type: "string"},
      {name: "postal", type: "string"},
      {name: "web_sessions", type: "string"},
      {name: "timezone", type: "string"},
      {name: "browser", type: "string"},
      {name: "browser_version", type: "string"},
      {name: "os", type: "string"},
      {name: "os_version", type: "string"},
      {name: "browser_language", type: "string"},
      {name: "lang", type: "string"},
    ]

    const content = (

Select field

oeoe

          {
            fields.map((o)=>

                              <Button onClick={(e)=> this.handleClick.bind(this)(e, o)}>
                                {o.name}
                              </Button>

            )
          }

    );

    return (

        <InlineDialog
          content={content}
          isOpen={this.state.dialogOpen}
          position="bottom left">

          <Button isLoading={false}
            appearance={'link'}
            onClick={this.toggleDialog}>

            {" "}
            Add filter
          </Button>
        </InlineDialog>

    );
  }
}

export default class SegmentManager extends Component {

  constructor(props){
    super(props)
  }

  handleClickOnSelectedFilter = (jwtToken)=>{
    const url = `/apps/${this.props.store.app.key}/segments/${this.props.store.segment.id}/${jwtToken}`
    //this.props.history.push(url)
  }

  render(){
    return

            <ButtonGroup>
              {
                this.props.actions.getPredicates().map((o, i)=>{
                    return <SegmentItemButton
                            key={i}
                            predicate={o}
                            open={ !o.comparison }
                            appearance={ o.comparison ? "primary" : "default"}
                            text={`Match: ${o.attribute} ${o.comparison ? o.comparison : '' } ${o.value ? o.value : ''}`}
                            updatePredicate={this.props.actions.updatePredicate}
                            deletePredicate={this.props.actions.deletePredicate}
                           />
                })
              }

              <InlineFilterDialog
                {...this.props}
                handleClick={this.handleClickOnSelectedFilter.bind(this)}
              />

              <SaveSegmentModal
                title="Save Segment"
                segment={this.props.store.segment}
                savePredicates={this.props.actions.savePredicates}
                deleteSegment={this.props.actions.deleteSegment}
              />

            </ButtonGroup>

              <ButtonGroup>

                {this.children}

              </ButtonGroup>

            {
              this.props.store.app.segments.map((o)=>(

{o.name}

                )
              )
            }

            Users {this.props.store.meta['total_count']}

  }
} <|endoftext|>


<commit_before>// @ngInject
export default class LanguageUtilsService {
  // @ngInject
  constructor($translate, $http, ENV) {
    this.$translate = $translate;
    this.$http = $http;
    this.ENV = ENV;
  }

  getCurrentLanguage() {
    return this.current;
  }

  setCurrentLanguage(language) {
    this.current = language;
    this.$translate.use(language.code);
    moment.locale(language.code);
    this.$http.defaults.headers.common['Accept-Language'] = language.code;
  }

  checkLanguage() {
    // Check if current language is listed in choices and
    // switch to default language if current choice is invalid.
    const key = this.$translate.storageKey();
    const storage = this.$translate.storage();
    const code = storage.get(key);
    const current = this.findLanguageByCode(code) || this.findLanguageByCode(this.ENV.defaultLanguage);
    this.setCurrentLanguage(current);
  }

  findLanguageByCode(code) {
    if (!code) {
      return;
    }
    return this.getChoices().filter(language => language.code === code)[0];
  }

  getChoices() {
    return this.ENV.languageChoices;
  }
}
<commit_msg>Fallback to first option in languageChoices list if defaultLanguage is invalid [WAL-1721]<commit_after>// @ngInject
export default class LanguageUtilsService {
  // @ngInject
  constructor($translate, $http, ENV) {
    this.$translate = $translate;
    this.$http = $http;
    this.ENV = ENV;
  }

  getCurrentLanguage() {
    return this.current;
  }

  setCurrentLanguage(language) {
    this.current = language;
    this.$translate.use(language.code);
    moment.locale(language.code);
    this.$http.defaults.headers.common['Accept-Language'] = language.code;
  }

  checkLanguage() {
    // Check if current language is listed in choices and
    // switch to default language if current choice is invalid.
    // Fallback to first option in languageChoices list if defaultLanguage is invalid.
    const key = this.$translate.storageKey();
    const storage = this.$translate.storage();
    const code = storage.get(key);
    const current = (
      this.findLanguageByCode(code)
        || this.findLanguageByCode(this.ENV.defaultLanguage)
        || this.getChoices()[0]
    );
    this.setCurrentLanguage(current);
  }

  findLanguageByCode(code) {
    if (!code) {
      return;
    }
    return this.getChoices().filter(language => language.code === code)[0];
  }

  getChoices() {
    return this.ENV.languageChoices;
  }
}
<|endoftext|>


<commit_before>'use strict';

require('../../app');
var angular = require('angular');

angular.module('deckApp')
  .controller('CloneServerGroupCtrl', function($scope, $modalInstance, _, $q, $exceptionHandler,
                                               accountService, orcaService, mortService, oortService, searchService,
                                               instanceTypeService, modalWizardService, securityGroupService,
                                               serverGroup, application, title) {
    $scope.title = title;
    $scope.healthCheckTypes = ['EC2', 'ELB'];
    $scope.terminationPolicies = ['OldestInstance', 'NewestInstance', 'OldestLaunchConfiguration', 'ClosestToNextInstanceHour', 'Default'];

    $scope.applicationName = application.name;

    $scope.state = {
      loaded: false,
      queryAllImages: false,
      submitting: false
    };

    $scope.taskStatus = {
      errorMessage: null,
      lastStage: null,
      hideProgressMessage: false,
      taskId: null,
      applicationName: application.name
    };

    var accountLoader = accountService.getRegionsKeyedByAccount().then(function(regionsKeyedByAccount) {
      $scope.accounts = _.keys(regionsKeyedByAccount);
      $scope.regionsKeyedByAccount = regionsKeyedByAccount;
    });

    var securityGroupLoader = securityGroupService.getAllSecurityGroups().then(function(securityGroups) {
      $scope.securityGroups = securityGroups;
    });

    var loadBalancerLoader = oortService.listLoadBalancers().then(function(loadBalancers) {
      $scope.loadBalancers = loadBalancers;
    });

    var subnetLoader = mortService.listSubnets().then(function(subnets) {
      $scope.subnets = subnets;
    });

    var imageLoader = searchService.search('oort', {q: application.name, type: 'namedImages', pageSize: 100000000}).then(function(searchResults) {
      $scope.packageImages = searchResults.results;
      if ($scope.packageImages.length === 0) {
        if (serverGroup) {
          searchService.search('oort', {q: serverGroup.launchConfig.imageId, type: 'namedImages'}).then(function (searchResults) {
            if (searchResults.results.length > 0) {
              var packageRegex = /(\w+)-?\w+/;
              $scope.imageName = searchResults.results[0].imageName;
              var match = packageRegex.exec($scope.imageName);
              $scope.applicationName = match[1];
              searchService.search('oort', {q: $scope.applicationName, type: 'namedImages', pageSize: 100000000}).then(function(searchResults) {
                $scope.packageImages = searchResults.results;
              });
            }
          });
        } else {
          $scope.state.queryAllImages = true;
        }
      }
    });

    $q.all([accountLoader, securityGroupLoader, loadBalancerLoader, subnetLoader, imageLoader]).then(function() {
      $scope.state.loaded = true;
      initializeCommand();
      initializeWizardState();
      initializeSelectOptions();
      initializeWatches();
    });

    function initializeWizardState() {
      if (serverGroup) {
        modalWizardService.getWizard().markComplete('location');
        modalWizardService.getWizard().markComplete('load-balancers');
        modalWizardService.getWizard().markComplete('security-groups');
        modalWizardService.getWizard().markComplete('instance-profile');
        modalWizardService.getWizard().markComplete('capacity');
        modalWizardService.getWizard().markComplete('advanced');
      }
    }

    function initializeWatches() {
      $scope.$watch('command.credentials', credentialsChanged);
      $scope.$watch('command.region', regionChanged);
      $scope.$watch('command.subnetType', subnetChanged);
    }

    function initializeSelectOptions() {
      credentialsChanged();
      regionChanged();
      configureSubnetPurposes();
      configureSecurityGroupOptions();
    }

    function credentialsChanged() {
      if ($scope.command.credentials) {
        $scope.regions = $scope.regionsKeyedByAccount[$scope.command.credentials].regions;
        if (!_($scope.regions).some({name: $scope.command.region})) {
          $scope.command.region = null;
        } else {
          regionChanged();
        }
      } else {
        $scope.command.region = null;
      }
    }

    function regionChanged() {
      configureSubnetPurposes();
      var currentZoneCount = $scope.command.availabilityZones ? $scope.command.availabilityZones.length : 0;
      if ($scope.command.region) {
        if (!_($scope.regionSubnetPurposes).some({purpose: $scope.command.subnetType})) {
          $scope.command.subnetType = null;
        }
        subnetChanged();
        configureInstanceTypes();
        configureAvailabilityZones();
        configureImages();
      } else {
        $scope.regionalAvailabilityZones = null;
      }
      $scope.command.availabilityZones = _.intersection($scope.command.availabilityZones, $scope.regionalAvailabilityZones);
      var newZoneCount = $scope.command.availabilityZones ? $scope.command.availabilityZones.length : 0;
      if (currentZoneCount !== newZoneCount) {
        modalWizardService.getWizard().markDirty('capacity');
      }
    }

    function subnetChanged() {
      var subnet = _($scope.subnets)
        .find({'purpose': $scope.command.subnetType, 'account': $scope.command.credentials, 'region': $scope.command.region});
      $scope.command.vpcId = subnet ? subnet.vpcId : null;
      configureSecurityGroupOptions();
      configureLoadBalancerOptions();
    }

    function configureAvailabilityZones() {
      $scope.regionalAvailabilityZones = _.find($scope.regionsKeyedByAccount[$scope.command.credentials].regions,
        {'name': $scope.command.region}).availabilityZones;
    }

    function configureSubnetPurposes() {
      if ($scope.command.region === null) {
        $scope.regionSubnetPurposes = null;
      }
      $scope.regionSubnetPurposes = _($scope.subnets)
        .filter({'account': $scope.command.credentials, 'region': $scope.command.region, 'target': 'ec2'})
        .pluck('purpose')
        .uniq()
        .map(function(purpose) { return { purpose: purpose, label: purpose };})
        .valueOf();
    }

    function configureSecurityGroupOptions() {
      var newRegionalSecurityGroups = _($scope.securityGroups[$scope.command.credentials].aws[$scope.command.region])
        .filter({'vpcId': $scope.command.vpcId || null})
        .valueOf();
      if ($scope.regionalSecurityGroups && $scope.command.securityGroups) {
        var previousCount = $scope.command.securityGroups.length;
        // not initializing - we are actually changing groups
        var matchedGroupNames = $scope.command.securityGroups.map(function(groupId) {
          return _($scope.regionalSecurityGroups).find({id: groupId}).name;
        }).map(function(groupName) {
          return _(newRegionalSecurityGroups).find({name: groupName});
        }).filter(function(group) {
          return group;
        }).map(function(group) {
          return group.id;
        });
        $scope.command.securityGroups = matchedGroupNames;
        if (matchedGroupNames.length !== previousCount) {
          modalWizardService.getWizard().markDirty('security-groups');
        }

      }

      $scope.regionalSecurityGroups = newRegionalSecurityGroups;
    }

    function configureLoadBalancerOptions() {
      var newLoadBalancers = _($scope.loadBalancers)
        .pluck('accounts')
        .flatten(true)
        .filter({'name': $scope.command.credentials})
        .pluck('regions')
        .flatten(true)
        .filter({'name': $scope.command.region})
        .pluck('loadBalancers')
        .flatten(true)
        .pluck('elb')
        .remove(undefined)
        .filter({'vpcid': $scope.command.vpcId})
        .pluck('loadBalancerName')
        .unique()
        .valueOf();

      if ($scope.regionalLoadBalancers && $scope.command.loadBalancers) {
        var previousCount = $scope.command.loadBalancers.length;
        $scope.command.loadBalancers = _.intersection(newLoadBalancers, $scope.command.loadBalancers);
        if ($scope.command.loadBalancers.length !== previousCount) {
          modalWizardService.getWizard().markDirty('load-balancers');
        }
      }

      $scope.regionalLoadBalancers = newLoadBalancers;
    }

    function configureImages() {
      if ($scope.command.region) {
        $scope.regionalImages = _.filter($scope.packageImages, {region: $scope.command.region});
        if ($scope.command.amiName && !_($scope.regionalImages).some({imageName: $scope.command.amiName})) {
          $scope.command.amiName = null;
        }
      } else {
        $scope.regionalImages = null;
        $scope.command.amiName = null;
      }
    }

    function configureInstanceTypes() {
      if ($scope.command.region) {
        instanceTypeService.getAvailableTypesForRegions([$scope.command.region]).then(function (result) {
          $scope.regionalInstanceTypes = result;
          if ($scope.command.instanceType && result.indexOf($scope.command.instanceType) === -1) {
            $scope.regionalInstanceTypes.push($scope.command.instanceType);
          }
        });
      }
    }

    function buildCommandFromExisting(serverGroup) {
      var asgNameRegex = /(\w+)(-v\d{3})?(-(\w+)?(-v\d{3})?(-(\w+))?)?(-v\d{3})?/;
      var match = asgNameRegex.exec(serverGroup.asg.autoScalingGroupName);
      var command = {
        'application': application.name,
        'stack': match[4],
        'freeFormDetails': match[7],
        'credentials': serverGroup.account,
        'cooldown': serverGroup.asg.defaultCooldown,
        'healthCheckGracePeriod': serverGroup.asg.healthCheckGracePeriod,
        'healthCheckType': serverGroup.asg.healthCheckType,
        'terminationPolicies': serverGroup.asg.terminationPolicies,
        'loadBalancers': serverGroup.asg.loadBalancerNames,
        'region': serverGroup.region,
        'availabilityZones': serverGroup.asg.availabilityZones,
        'capacity': {
          'min': serverGroup.asg.minSize,
          'max': serverGroup.asg.maxSize,
          'desired': serverGroup.asg.desiredCapacity
        },
        'allImageSelection': null,
        'instanceProfile': 'custom'
      };
      if (serverGroup.launchConfig) {
        var amiName = null;
        if (serverGroup.launchConfig.imageId) {
          var foundImage = _($scope.packageImages).find({'imageId': serverGroup.launchConfig.imageId});
          if (foundImage) {
            amiName = foundImage.imageName;
          }
        }
        angular.extend(command, {
          'instanceType': serverGroup.launchConfig.instanceType,
          'iamRole': serverGroup.launchConfig.iamInstanceProfile,
          'keyPair': serverGroup.launchConfig.keyName,
          'associatePublicIpAddress': serverGroup.launchConfig.associatePublicIpAddress,
          'ramdiskId': serverGroup.launchConfig.ramdiskId,
          'instanceMonitoring': serverGroup.launchConfig.instanceMonitoring.enabled,
          'ebsOptimized': serverGroup.launchConfig.ebsOptimized,
          'amiName': amiName
        });
      }
      var vpcZoneIdentifier = serverGroup.asg.vpczoneIdentifier;
      if (vpcZoneIdentifier !== '') {
        var subnetId = vpcZoneIdentifier.split(',')[0];
        var subnet = _($scope.subnets).find({'id': subnetId});
        command.subnetType = subnet.purpose;
        command.vpcId = subnet.vpcId;
      } else {
        command.subnetType = '';
        command.vpcId = null;
      }
      if (serverGroup.launchConfig && serverGroup.launchConfig.securityGroups.length) {
        command.securityGroups = serverGroup.launchConfig.securityGroups;
      }
      return command;
    }

    function createCommandTemplate() {
      return {
        'application': application.name,
        'credentials': 'test',
        'region': 'us-east-1',
        'availabilityZones': [],
        'capacity': {
          'min': 0,
          'max': 0,
          'desired': 0
        },
        'cooldown': 10,
        'healthCheckType': 'EC2',
        'healthCheckGracePeriod': 600,
        'instanceMonitoring': false,
        'ebsOptimized': false,

        //These two should not be hard coded here, and keyPair options should be loaded from AWS
        'iamRole': 'BaseIAMRole',
        'keyPair': 'nf-test-keypair-a',

        'terminationPolicies': ['Default'],
        'vpcId': null,
        allImageSelection: null
      };
    }

    function initializeCommand() {
      if (serverGroup) {
        $scope.command = buildCommandFromExisting(serverGroup);
      } else {
        $scope.command = createCommandTemplate();
      }
    }

    this.isValid = function () {
      return $scope.command && ($scope.command.amiName !== null) && ($scope.command.application !== null) &&
        ($scope.command.credentials !== null) && ($scope.command.instanceType !== null) &&
        ($scope.command.region !== null) && ($scope.command.availabilityZones !== null) &&
        ($scope.command.capacity.min !== null) && ($scope.command.capacity.max !== null) &&
        ($scope.command.capacity.desired !== null) &&
        modalWizardService.getWizard().isComplete();
    };

    this.showSubmitButton = function () {
      return modalWizardService.getWizard().allPagesVisited();
    };

    this.clone = function () {

      $scope.state.submitting = true;
      $scope.taskStatus.errorMessage = null;
      $scope.taskStatus.hideProgressMessage = false;
      $scope.taskStatus.taskId = null;

      var command = angular.copy($scope.command);
      var description;
      if (serverGroup) {
        description = 'Create Cloned Server Group from ' + serverGroup.asg.autoScalingGroupName;
        command.type = 'copyLastAsg';
        command.source = {
          'account': serverGroup.account,
          'region': serverGroup.region,
          'asgName': serverGroup.asg.autoScalingGroupName
        };
      } else {
        command.type = 'deploy';
        var asgName = application.name;
        if (command.stack) {
          asgName += '-' + command.stack;
        }
        if (!command.stack && command.freeFormDetails) {
          asgName += '-';
        }
        if (command.freeFormDetails) {
          asgName += '-' + command.freeFormDetails;
        }
        description = 'Create New Server Group in cluster ' + asgName;
      }
      command.availabilityZones = {};
      command.availabilityZones[command.region] = $scope.command.availabilityZones;
      orcaService.cloneServerGroup(command, application.name, description)
        .then(function (task) {
          $scope.taskStatus.taskId = task.id;
          task.watchForKatoCompletion().then(
            function() { // kato succeeded
              $modalInstance.close();
              task.watchForForceRefresh().then(
                function() { // cache has been refreshed; object should be available
                  application.refreshImmediately();
                },
                function(task) { // cache refresh never happened?
                  $exceptionHandler('task failed to force cache refresh:', task);
                }
              );
            },
            function(updatedTask) { // kato failed
              $scope.state.submitting = false;
              $scope.taskStatus.errorMessage = updatedTask.statusMessage || 'There was an unknown server error.';
              $scope.taskStatus.lastStage = null;
            },
            function(notification) {
              $scope.taskStatus.lastStage = notification;
            }
          );
        },
        function(error) {
          $scope.state.submitting = false;
          $scope.taskStatus.errorMessage = error.message || 'There was an unknown server error.';
          $scope.taskStatus.lastStage = null;
          $exceptionHandler('Post to pond failed:', error);
        }
      );
    };

    this.cancel = function () {
      $modalInstance.dismiss();
    };
  });
<commit_msg>remove parameters that are not used by pond<commit_after>'use strict';

require('../../app');
var angular = require('angular');

angular.module('deckApp')
  .controller('CloneServerGroupCtrl', function($scope, $modalInstance, _, $q, $exceptionHandler,
                                               accountService, orcaService, mortService, oortService, searchService,
                                               instanceTypeService, modalWizardService, securityGroupService,
                                               serverGroup, application, title) {
    $scope.title = title;
    $scope.healthCheckTypes = ['EC2', 'ELB'];
    $scope.terminationPolicies = ['OldestInstance', 'NewestInstance', 'OldestLaunchConfiguration', 'ClosestToNextInstanceHour', 'Default'];

    $scope.applicationName = application.name;

    $scope.state = {
      loaded: false,
      queryAllImages: false,
      submitting: false
    };

    $scope.taskStatus = {
      errorMessage: null,
      lastStage: null,
      hideProgressMessage: false,
      taskId: null,
      applicationName: application.name
    };

    var accountLoader = accountService.getRegionsKeyedByAccount().then(function(regionsKeyedByAccount) {
      $scope.accounts = _.keys(regionsKeyedByAccount);
      $scope.regionsKeyedByAccount = regionsKeyedByAccount;
    });

    var securityGroupLoader = securityGroupService.getAllSecurityGroups().then(function(securityGroups) {
      $scope.securityGroups = securityGroups;
    });

    var loadBalancerLoader = oortService.listLoadBalancers().then(function(loadBalancers) {
      $scope.loadBalancers = loadBalancers;
    });

    var subnetLoader = mortService.listSubnets().then(function(subnets) {
      $scope.subnets = subnets;
    });

    var imageLoader = searchService.search('oort', {q: application.name, type: 'namedImages', pageSize: 100000000}).then(function(searchResults) {
      $scope.packageImages = searchResults.results;
      if ($scope.packageImages.length === 0) {
        if (serverGroup) {
          searchService.search('oort', {q: serverGroup.launchConfig.imageId, type: 'namedImages'}).then(function (searchResults) {
            if (searchResults.results.length > 0) {
              var packageRegex = /(\w+)-?\w+/;
              $scope.imageName = searchResults.results[0].imageName;
              var match = packageRegex.exec($scope.imageName);
              $scope.applicationName = match[1];
              searchService.search('oort', {q: $scope.applicationName, type: 'namedImages', pageSize: 100000000}).then(function(searchResults) {
                $scope.packageImages = searchResults.results;
              });
            }
          });
        } else {
          $scope.state.queryAllImages = true;
        }
      }
    });

    $q.all([accountLoader, securityGroupLoader, loadBalancerLoader, subnetLoader, imageLoader]).then(function() {
      $scope.state.loaded = true;
      initializeCommand();
      initializeWizardState();
      initializeSelectOptions();
      initializeWatches();
    });

    function initializeWizardState() {
      if (serverGroup) {
        modalWizardService.getWizard().markComplete('location');
        modalWizardService.getWizard().markComplete('load-balancers');
        modalWizardService.getWizard().markComplete('security-groups');
        modalWizardService.getWizard().markComplete('instance-profile');
        modalWizardService.getWizard().markComplete('capacity');
        modalWizardService.getWizard().markComplete('advanced');
      }
    }

    function initializeWatches() {
      $scope.$watch('command.credentials', credentialsChanged);
      $scope.$watch('command.region', regionChanged);
      $scope.$watch('command.subnetType', subnetChanged);
    }

    function initializeSelectOptions() {
      credentialsChanged();
      regionChanged();
      configureSubnetPurposes();
      configureSecurityGroupOptions();
    }

    function credentialsChanged() {
      if ($scope.command.credentials) {
        $scope.regions = $scope.regionsKeyedByAccount[$scope.command.credentials].regions;
        if (!_($scope.regions).some({name: $scope.command.region})) {
          $scope.command.region = null;
        } else {
          regionChanged();
        }
      } else {
        $scope.command.region = null;
      }
    }

    function regionChanged() {
      configureSubnetPurposes();
      var currentZoneCount = $scope.command.availabilityZones ? $scope.command.availabilityZones.length : 0;
      if ($scope.command.region) {
        if (!_($scope.regionSubnetPurposes).some({purpose: $scope.command.subnetType})) {
          $scope.command.subnetType = null;
        }
        subnetChanged();
        configureInstanceTypes();
        configureAvailabilityZones();
        configureImages();
      } else {
        $scope.regionalAvailabilityZones = null;
      }
      $scope.command.availabilityZones = _.intersection($scope.command.availabilityZones, $scope.regionalAvailabilityZones);
      var newZoneCount = $scope.command.availabilityZones ? $scope.command.availabilityZones.length : 0;
      if (currentZoneCount !== newZoneCount) {
        modalWizardService.getWizard().markDirty('capacity');
      }
    }

    function subnetChanged() {
      var subnet = _($scope.subnets)
        .find({'purpose': $scope.command.subnetType, 'account': $scope.command.credentials, 'region': $scope.command.region});
      $scope.command.vpcId = subnet ? subnet.vpcId : null;
      configureSecurityGroupOptions();
      configureLoadBalancerOptions();
    }

    function configureAvailabilityZones() {
      $scope.regionalAvailabilityZones = _.find($scope.regionsKeyedByAccount[$scope.command.credentials].regions,
        {'name': $scope.command.region}).availabilityZones;
    }

    function configureSubnetPurposes() {
      if ($scope.command.region === null) {
        $scope.regionSubnetPurposes = null;
      }
      $scope.regionSubnetPurposes = _($scope.subnets)
        .filter({'account': $scope.command.credentials, 'region': $scope.command.region, 'target': 'ec2'})
        .pluck('purpose')
        .uniq()
        .map(function(purpose) { return { purpose: purpose, label: purpose };})
        .valueOf();
    }

    function configureSecurityGroupOptions() {
      var newRegionalSecurityGroups = _($scope.securityGroups[$scope.command.credentials].aws[$scope.command.region])
        .filter({'vpcId': $scope.command.vpcId || null})
        .valueOf();
      if ($scope.regionalSecurityGroups && $scope.command.securityGroups) {
        var previousCount = $scope.command.securityGroups.length;
        // not initializing - we are actually changing groups
        var matchedGroupNames = $scope.command.securityGroups.map(function(groupId) {
          return _($scope.regionalSecurityGroups).find({id: groupId}).name;
        }).map(function(groupName) {
          return _(newRegionalSecurityGroups).find({name: groupName});
        }).filter(function(group) {
          return group;
        }).map(function(group) {
          return group.id;
        });
        $scope.command.securityGroups = matchedGroupNames;
        if (matchedGroupNames.length !== previousCount) {
          modalWizardService.getWizard().markDirty('security-groups');
        }

      }

      $scope.regionalSecurityGroups = newRegionalSecurityGroups;
    }

    function configureLoadBalancerOptions() {
      var newLoadBalancers = _($scope.loadBalancers)
        .pluck('accounts')
        .flatten(true)
        .filter({'name': $scope.command.credentials})
        .pluck('regions')
        .flatten(true)
        .filter({'name': $scope.command.region})
        .pluck('loadBalancers')
        .flatten(true)
        .pluck('elb')
        .remove(undefined)
        .filter({'vpcid': $scope.command.vpcId})
        .pluck('loadBalancerName')
        .unique()
        .valueOf();

      if ($scope.regionalLoadBalancers && $scope.command.loadBalancers) {
        var previousCount = $scope.command.loadBalancers.length;
        $scope.command.loadBalancers = _.intersection(newLoadBalancers, $scope.command.loadBalancers);
        if ($scope.command.loadBalancers.length !== previousCount) {
          modalWizardService.getWizard().markDirty('load-balancers');
        }
      }

      $scope.regionalLoadBalancers = newLoadBalancers;
    }

    function configureImages() {
      if ($scope.command.region) {
        $scope.regionalImages = _.filter($scope.packageImages, {region: $scope.command.region});
        if ($scope.command.amiName && !_($scope.regionalImages).some({imageName: $scope.command.amiName})) {
          $scope.command.amiName = null;
        }
      } else {
        $scope.regionalImages = null;
        $scope.command.amiName = null;
      }
    }

    function configureInstanceTypes() {
      if ($scope.command.region) {
        instanceTypeService.getAvailableTypesForRegions([$scope.command.region]).then(function (result) {
          $scope.regionalInstanceTypes = result;
          if ($scope.command.instanceType && result.indexOf($scope.command.instanceType) === -1) {
            $scope.regionalInstanceTypes.push($scope.command.instanceType);
          }
        });
      }
    }

    function buildCommandFromExisting(serverGroup) {
      var asgNameRegex = /(\w+)(-v\d{3})?(-(\w+)?(-v\d{3})?(-(\w+))?)?(-v\d{3})?/;
      var match = asgNameRegex.exec(serverGroup.asg.autoScalingGroupName);
      var command = {
        'application': application.name,
        'stack': match[4],
        'freeFormDetails': match[7],
        'credentials': serverGroup.account,
        'cooldown': serverGroup.asg.defaultCooldown,
        'healthCheckGracePeriod': serverGroup.asg.healthCheckGracePeriod,
        'healthCheckType': serverGroup.asg.healthCheckType,
        'terminationPolicies': serverGroup.asg.terminationPolicies,
        'loadBalancers': serverGroup.asg.loadBalancerNames,
        'region': serverGroup.region,
        'availabilityZones': serverGroup.asg.availabilityZones,
        'capacity': {
          'min': serverGroup.asg.minSize,
          'max': serverGroup.asg.maxSize,
          'desired': serverGroup.asg.desiredCapacity
        },
        'allImageSelection': null,
        'instanceProfile': 'custom'
      };
      if (serverGroup.launchConfig) {
        var amiName = null;
        if (serverGroup.launchConfig.imageId) {
          var foundImage = _($scope.packageImages).find({'imageId': serverGroup.launchConfig.imageId});
          if (foundImage) {
            amiName = foundImage.imageName;
          }
        }
        angular.extend(command, {
          'instanceType': serverGroup.launchConfig.instanceType,
          'iamRole': serverGroup.launchConfig.iamInstanceProfile,
          'keyPair': serverGroup.launchConfig.keyName,
          'associatePublicIpAddress': serverGroup.launchConfig.associatePublicIpAddress,
          'ramdiskId': serverGroup.launchConfig.ramdiskId,
          'instanceMonitoring': serverGroup.launchConfig.instanceMonitoring.enabled,
          'ebsOptimized': serverGroup.launchConfig.ebsOptimized,
          'amiName': amiName
        });
      }
      var vpcZoneIdentifier = serverGroup.asg.vpczoneIdentifier;
      if (vpcZoneIdentifier !== '') {
        var subnetId = vpcZoneIdentifier.split(',')[0];
        var subnet = _($scope.subnets).find({'id': subnetId});
        command.subnetType = subnet.purpose;
        command.vpcId = subnet.vpcId;
      } else {
        command.subnetType = '';
        command.vpcId = null;
      }
      if (serverGroup.launchConfig && serverGroup.launchConfig.securityGroups.length) {
        command.securityGroups = serverGroup.launchConfig.securityGroups;
      }
      return command;
    }

    function createCommandTemplate() {
      return {
        'application': application.name,
        'credentials': 'test',
        'region': 'us-east-1',
        'availabilityZones': [],
        'capacity': {
          'min': 0,
          'max': 0,
          'desired': 0
        },
        'cooldown': 10,
        'healthCheckType': 'EC2',
        'healthCheckGracePeriod': 600,
        'instanceMonitoring': false,
        'ebsOptimized': false,

        //These two should not be hard coded here, and keyPair options should be loaded from AWS
        'iamRole': 'BaseIAMRole',
        'keyPair': 'nf-test-keypair-a',

        'terminationPolicies': ['Default'],
        'vpcId': null,
        allImageSelection: null
      };
    }

    function initializeCommand() {
      if (serverGroup) {
        $scope.command = buildCommandFromExisting(serverGroup);
      } else {
        $scope.command = createCommandTemplate();
      }
    }

    this.isValid = function () {
      return $scope.command && ($scope.command.amiName !== null) && ($scope.command.application !== null) &&
        ($scope.command.credentials !== null) && ($scope.command.instanceType !== null) &&
        ($scope.command.region !== null) && ($scope.command.availabilityZones !== null) &&
        ($scope.command.capacity.min !== null) && ($scope.command.capacity.max !== null) &&
        ($scope.command.capacity.desired !== null) &&
        modalWizardService.getWizard().isComplete();
    };

    this.showSubmitButton = function () {
      return modalWizardService.getWizard().allPagesVisited();
    };

    this.clone = function () {

      $scope.state.submitting = true;
      $scope.taskStatus.errorMessage = null;
      $scope.taskStatus.hideProgressMessage = false;
      $scope.taskStatus.taskId = null;

      var command = angular.copy($scope.command);
      var description;
      if (serverGroup) {
        description = 'Create Cloned Server Group from ' + serverGroup.asg.autoScalingGroupName;
        command.type = 'copyLastAsg';
        command.source = {
          'account': serverGroup.account,
          'region': serverGroup.region,
          'asgName': serverGroup.asg.autoScalingGroupName
        };
      } else {
        command.type = 'deploy';
        var asgName = application.name;
        if (command.stack) {
          asgName += '-' + command.stack;
        }
        if (!command.stack && command.freeFormDetails) {
          asgName += '-';
        }
        if (command.freeFormDetails) {
          asgName += '-' + command.freeFormDetails;
        }
        description = 'Create New Server Group in cluster ' + asgName;
      }
      command.availabilityZones = {};
      command.availabilityZones[command.region] = $scope.command.availabilityZones;
      delete command.region;
      delete command.allImageSelection;
      delete command.instanceProfile;
      orcaService.cloneServerGroup(command, application.name, description)
        .then(function (task) {
          $scope.taskStatus.taskId = task.id;
          task.watchForKatoCompletion().then(
            function() { // kato succeeded
              $modalInstance.close();
              task.watchForForceRefresh().then(
                function() { // cache has been refreshed; object should be available
                  application.refreshImmediately();
                },
                function(task) { // cache refresh never happened?
                  $exceptionHandler('task failed to force cache refresh:', task);
                }
              );
            },
            function(updatedTask) { // kato failed
              $scope.state.submitting = false;
              $scope.taskStatus.errorMessage = updatedTask.statusMessage || 'There was an unknown server error.';
              $scope.taskStatus.lastStage = null;
            },
            function(notification) {
              $scope.taskStatus.lastStage = notification;
            }
          );
        },
        function(error) {
          $scope.state.submitting = false;
          $scope.taskStatus.errorMessage = error.message || 'There was an unknown server error.';
          $scope.taskStatus.lastStage = null;
          $exceptionHandler('Post to pond failed:', error);
        }
      );
    };

    this.cancel = function () {
      $modalInstance.dismiss();
    };
  });
<|endoftext|>