<commit_before>/*
 * Copyright 2020 ThoughtWorks, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {ApiRequestBuilder, ApiResult, ApiVersion, ErrorResponse} from "helpers/api_request_builder";
import {SparkRoutes} from "helpers/spark_routes";
import m from "mithril";
import Stream from "mithril/stream";
import {PipelineGroupCRUD} from "models/admin_pipelines/pipeline_groups_crud";
import {headerMeta} from "models/current_user_permissions";
import {PipelineGroups, PipelineStructureWithAdditionalInfo} from "models/internal_pipeline_structure/pipeline_structure";
import {PipelineStructureCRUD} from "models/internal_pipeline_structure/pipeline_structure_crud";
import {PipelineGroupCRUD as PipelineGroupCacheCRUD} from "models/pipeline_configs/pipeline_groups_cache";
import {ExtensionTypeString} from "models/shared/plugin_infos_new/extension_type";
import {PluginInfos} from "models/shared/plugin_infos_new/plugin_info";
import {PluginInfoCRUD} from "models/shared/plugin_infos_new/plugin_info_crud";
import {AnchorVM, ScrollManager} from "views/components/anchor/anchor";
import * as Buttons from "views/components/buttons";
import {ButtonIcon} from "views/components/buttons";
import {FlashMessage, MessageType} from "views/components/flash_message";
import {HeaderPanel} from "views/components/header_panel";
import {DeleteConfirmModal} from "views/components/modal/delete_confirm_modal";
import {Attrs, PipelineGroupsWidget, PipelinesScrollOptions} from "views/pages/admin_pipelines/admin_pipelines_widget";
import {
  ClonePipelineConfigModal,
  CreatePipelineGroupModal,
  DeletePipelineGroupModal,
  DownloadPipelineModal,
  ExtractTemplateModal,
  MoveConfirmModal
} from "views/pages/admin_pipelines/modals";
import {Page, PageState} from "views/pages/page";
import buttonStyle from "views/pages/pipelines/actions.scss";
import {EditPipelineGroupModal} from "./admin_pipelines/edit_pipeline_group_modal";

interface State extends Attrs {
  pluginInfos: Stream<PluginInfos>;
  usersAutoCompleteHelper: Stream<string[]>;
  rolesAutoCompleteHelper: Stream<string[]>;
}

const sm: ScrollManager = new AnchorVM();

export class AdminPipelinesPage extends Page<null, State> {
  private operation: string = "";

  componentToDisplay(vnode: m.Vnode<null, State>): m.Children {
    this.parseRepoLink(sm);
    const scrollOptions: PipelinesScrollOptions = {
      sm,
      shouldOpenEditView: this.operation === "edit"
    };
    return (
      <div>
        <FlashMessage type={this.flashMessage.type} message={this.flashMessage.message}/>
        <PipelineGroupsWidget {...vnode.state} scrollOptions={scrollOptions}/>
      </div>
    );
  }

  pageName(): string {
    return "Pipelines";
  }

  fetchData(vnode: m.Vnode<null, State>): Promise<any> {
    this.pageState = PageState.LOADING;

    vnode.state.pipelineGroups          = Stream(new PipelineGroups());
    vnode.state.pluginInfos             = Stream(new PluginInfos());
    vnode.state.usersAutoCompleteHelper = Stream();
    vnode.state.rolesAutoCompleteHelper = Stream();

    const onOperationError = (errorResponse: ErrorResponse) => {
      vnode.state.onError(JSON.parse(errorResponse.body!).message);
    };

    vnode.state.doEditPipelineGroup = (groupName: string) => {
      const pipelineGroup             = vnode.state.pipelineGroups().find((pipelineGroup) => pipelineGroup.name() === groupName);
      const containsPipelinesRemotely = pipelineGroup ? pipelineGroup.containsRemotelyDefinedPipelines() : false;

      this.pageState = PageState.LOADING;
      PipelineGroupCRUD.get(groupName).then((result) => {
        this.pageState = PageState.OK;
        result.do((successResponse) => {
          new EditPipelineGroupModal(successResponse.body.object, successResponse.body.etag, vnode.state.usersAutoCompleteHelper(), vnode.state.rolesAutoCompleteHelper(), vnode.state.onSuccessfulSave, containsPipelinesRemotely).render();
        }, () => {
          this.setErrorState();
        });
      });
    };

    vnode.state.createPipelineGroup = () => {
      const modal = new CreatePipelineGroupModal((groupName) => {
        PipelineGroupCacheCRUD
          .create({name: groupName})
          .then((response) => {
            response.do(
              (successResponse) => {
                const msg = <span>The pipeline group <em>{groupName}</em> was created successfully.</span>;
                vnode.state.onSuccessfulSave(msg);
              },
              onOperationError);
          })
        ;
      });
      modal.render();
    };

    vnode.state.createPipelineInGroup = (groupName) => {
      window.location.href = SparkRoutes.newCreatePipelinePath(groupName);
    };

    vnode.state.doMovePipeline = (sourceGroup, pipeline) => {
      new MoveConfirmModal(vnode.state.pipelineGroups(),
                           sourceGroup,
                           pipeline,
                           vnode.state.onSuccessfulSave)
        .render();
    };

    vnode.state.onError = (msg: m.Children) => {
      this.flashMessage.setMessage(MessageType.alert, msg);
    };

    vnode.state.onSuccessfulSave = (msg: m.Children) => {
      this.flashMessage.setMessage(MessageType.success, msg);
      this.fetchData(vnode);
    };

    vnode.state.doDeleteGroup = (group) => {
      new DeletePipelineGroupModal(group.name(), vnode.state.onSuccessfulSave)
        .render();
    };

    vnode.state.doDeletePipeline = (pipeline) => {
      const message = <span>Are you sure you want to delete the pipeline <em>{pipeline.name()}</em>?</span>;

      const modal: DeleteConfirmModal = new DeleteConfirmModal(message, () => {
        return ApiRequestBuilder.DELETE(SparkRoutes.adminPipelineConfigPath(pipeline.name()), ApiVersion.latest)
                                .then((result) => {
                                  result.do(
                                    () => vnode.state.onSuccessfulSave(
                                      <span>The pipeline group <em>{pipeline.name()}</em> was deleted successfully!</span>
                                    ),
                                    onOperationError
                                  );

                                })
                                .finally(modal.close.bind(modal));
      });

      modal.render();
    };

    vnode.state.doExtractPipeline = (pipeline) => {
      const extractOperation = (templateName: string) => {
        ApiRequestBuilder.PUT(SparkRoutes.adminExtractTemplateFromPipelineConfigPath(pipeline.name()),
                              ApiVersion.latest,
                              {
                                payload: {
                                  template_name: templateName
                                }<commit_msg>Fix typo from delete pipeline message.<commit_after>/*
 * Copyright 2020 ThoughtWorks, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import {ApiRequestBuilder, ApiResult, ApiVersion, ErrorResponse} from "helpers/api_request_builder";
import {SparkRoutes} from "helpers/spark_routes";
import m from "mithril";
import Stream from "mithril/stream";
import {PipelineGroupCRUD} from "models/admin_pipelines/pipeline_groups_crud";
import {headerMeta} from "models/current_user_permissions";
import {PipelineGroups, PipelineStructureWithAdditionalInfo} from "models/internal_pipeline_structure/pipeline_structure";
import {PipelineStructureCRUD} from "models/internal_pipeline_structure/pipeline_structure_crud";
import {PipelineGroupCRUD as PipelineGroupCacheCRUD} from "models/pipeline_configs/pipeline_groups_cache";
import {ExtensionTypeString} from "models/shared/plugin_infos_new/extension_type";
import {PluginInfos} from "models/shared/plugin_infos_new/plugin_info";
import {PluginInfoCRUD} from "models/shared/plugin_infos_new/plugin_info_crud";
import {AnchorVM, ScrollManager} from "views/components/anchor/anchor";
import * as Buttons from "views/components/buttons";
import {ButtonIcon} from "views/components/buttons";
import {FlashMessage, MessageType} from "views/components/flash_message";
import {HeaderPanel} from "views/components/header_panel";
import {DeleteConfirmModal} from "views/components/modal/delete_confirm_modal";
import {Attrs, PipelineGroupsWidget, PipelinesScrollOptions} from "views/pages/admin_pipelines/admin_pipelines_widget";
import {
  ClonePipelineConfigModal,
  CreatePipelineGroupModal,
  DeletePipelineGroupModal,
  DownloadPipelineModal,
  ExtractTemplateModal,
  MoveConfirmModal
} from "views/pages/admin_pipelines/modals";
import {Page, PageState} from "views/pages/page";
import buttonStyle from "views/pages/pipelines/actions.scss";
import {EditPipelineGroupModal} from "./admin_pipelines/edit_pipeline_group_modal";

interface State extends Attrs {
  pluginInfos: Stream<PluginInfos>;
  usersAutoCompleteHelper: Stream<string[]>;
  rolesAutoCompleteHelper: Stream<string[]>;
}

const sm: ScrollManager = new AnchorVM();

export class AdminPipelinesPage extends Page<null, State> {
  private operation: string = "";

  componentToDisplay(vnode: m.Vnode<null, State>): m.Children {
    this.parseRepoLink(sm);
    const scrollOptions: PipelinesScrollOptions = {
      sm,
      shouldOpenEditView: this.operation === "edit"
    };
    return (
      <div>
        <FlashMessage type={this.flashMessage.type} message={this.flashMessage.message}/>
        <PipelineGroupsWidget {...vnode.state} scrollOptions={scrollOptions}/>
      </div>
    );
  }

  pageName(): string {
    return "Pipelines";
  }

  fetchData(vnode: m.Vnode<null, State>): Promise<any> {
    this.pageState = PageState.LOADING;

    vnode.state.pipelineGroups          = Stream(new PipelineGroups());
    vnode.state.pluginInfos             = Stream(new PluginInfos());
    vnode.state.usersAutoCompleteHelper = Stream();
    vnode.state.rolesAutoCompleteHelper = Stream();

    const onOperationError = (errorResponse: ErrorResponse) => {
      vnode.state.onError(JSON.parse(errorResponse.body!).message);
    };

    vnode.state.doEditPipelineGroup = (groupName: string) => {
      const pipelineGroup             = vnode.state.pipelineGroups().find((pipelineGroup) => pipelineGroup.name() === groupName);
      const containsPipelinesRemotely = pipelineGroup ? pipelineGroup.containsRemotelyDefinedPipelines() : false;

      this.pageState = PageState.LOADING;
      PipelineGroupCRUD.get(groupName).then((result) => {
        this.pageState = PageState.OK;
        result.do((successResponse) => {
          new EditPipelineGroupModal(successResponse.body.object, successResponse.body.etag, vnode.state.usersAutoCompleteHelper(), vnode.state.rolesAutoCompleteHelper(), vnode.state.onSuccessfulSave, containsPipelinesRemotely).render();
        }, () => {
          this.setErrorState();
        });
      });
    };

    vnode.state.createPipelineGroup = () => {
      const modal = new CreatePipelineGroupModal((groupName) => {
        PipelineGroupCacheCRUD
          .create({name: groupName})
          .then((response) => {
            response.do(
              (successResponse) => {
                const msg = <span>The pipeline group <em>{groupName}</em> was created successfully.</span>;
                vnode.state.onSuccessfulSave(msg);
              },
              onOperationError);
          })
        ;
      });
      modal.render();
    };

    vnode.state.createPipelineInGroup = (groupName) => {
      window.location.href = SparkRoutes.newCreatePipelinePath(groupName);
    };

    vnode.state.doMovePipeline = (sourceGroup, pipeline) => {
      new MoveConfirmModal(vnode.state.pipelineGroups(),
                           sourceGroup,
                           pipeline,
                           vnode.state.onSuccessfulSave)
        .render();
    };

    vnode.state.onError = (msg: m.Children) => {
      this.flashMessage.setMessage(MessageType.alert, msg);
    };

    vnode.state.onSuccessfulSave = (msg: m.Children) => {
      this.flashMessage.setMessage(MessageType.success, msg);
      this.fetchData(vnode);
    };

    vnode.state.doDeleteGroup = (group) => {
      new DeletePipelineGroupModal(group.name(), vnode.state.onSuccessfulSave)
        .render();
    };

    vnode.state.doDeletePipeline = (pipeline) => {
      const message = <span>Are you sure you want to delete the pipeline <em>{pipeline.name()}</em>?</span>;

      const modal: DeleteConfirmModal = new DeleteConfirmModal(message, () => {
        return ApiRequestBuilder.DELETE(SparkRoutes.adminPipelineConfigPath(pipeline.name()), ApiVersion.latest)
                                .then((result) => {
                                  result.do(
                                    () => vnode.state.onSuccessfulSave(
                                      <span>The pipeline <em>{pipeline.name()}</em> was deleted successfully!</span>
                                    ),
                                    onOperationError
                                  );

                                })
                                .finally(modal.close.bind(modal));
      });

      modal.render();
    };

    vnode.state.doExtractPipeline = (pipeline) => {
      const extractOperation = (templateName: string) => {
        ApiRequestBuilder.PUT(SparkRoutes.adminExtractTemplateFromPipelineConfigPath(pipeline.name()),
                              ApiVersion.latest,
                              {
                                payload: {
                                  template_name: templateName
                                }
{'fraction_non_alphanumeric': 0.10931174089068826, 'fraction_numerical': 0.0010979208124614012, 'mean_word_length': 2.9240710823909533, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 91, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1221854', 'n_tokens_mistral': 3966, 'n_tokens_neox': 3912, 'n_words': 780}