<html>

<head>
  <script src="/unpkg.com/@steedos-builder/fiddle@0.0.5/dist/builder-fiddle.umd.js"></script>
  <script src="/unpkg.com/axios@0.26.1/dist/axios.min.js"></script>
  <script src="/unpkg.com/flowbite@2.3.0/dist/flowbite.min.js"></script>
  <script src="/unpkg.com/lodash@4.17.21/lodash.min.js"></script>
  <script src="https://cdn.tailwindcss.com"></script>
  <link href="/toast/toastr.min.css" rel="stylesheet" />
  <script src="/jquery.min.js"></script>
  <script src="/toast/toastr.min.js"></script>
  <script>
    window._disabledFields = [
      'autonumber', 'formula', 'summary'
    ]
  </script>
  <style>
    #toast-container.toast-bottom-center>div,
    #toast-container.toast-top-center>div {
      width: 450px;
      opacity: 1;
    }
  </style>
</head>

<body>
  <!-- Main modal -->
  <div id="fieldLayoutModal" tabindex="-1" aria-hidden="true"
    class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
    <div class="relative p-4 w-full max-w-2xl max-h-full">
      <!-- Modal content -->
      <div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
        <!-- Modal header -->
        <div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600">
          <h3 class="text-xl font-semibold text-gray-900 dark:text-white">
            字段保存结果
          </h3>
          <button type="button"
            class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"
            data-modal-hide="fieldLayoutModal">
            <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
              <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
            </svg>
            <span class="sr-only">Close modal</span>
          </button>
        </div>
        <!-- Modal body -->
        <div class="p-4 md:p-5 space-y-4">
          <ul class="space-y-4 text-gray-500 list-disc list-inside dark:text-gray-400" id="fieldLayoutList">
          </ul>
        </div>
      </div>
    </div>
  </div>
  <builder-fiddle host="<%=builderHost%>"></builder-fiddle>
  <script>
    const useOpenAPI = <%=(useOpenAPI === "true" || useOpenAPI === true) %>;
    const settings = {
      assetUrls: "<%=assetUrls%>",
      rootUrl: "<%=rootUrl%>",
      userId: "<%=userId%>",
      tenantId: "<%=tenantId%>",
      authToken: "<%=authToken%>",
      messageOnly: true,
      useOpenAPI: useOpenAPI,
      id: "<%=id%>",
      pageId: "<%=id%>",
      hiddenDeploy: true,
      title: "<%=locale%>" === 'zh-CN' ? '流程表单设计器': 'Flow Form Designer',
      saveText: "<%=locale%>" === 'zh-CN' ? '保存': 'Save',
      deployText: "<%=locale%>" === 'zh-CN' ? '发布': 'Deploy',
    };

    const getArgumentsList = (func)=>{
      let funcString;
      if (typeof func === 'function') {
        funcString = func.toString();
      } else {
        funcString = func;
      }
      const regExp = /function\s*\w*\(([\s\S]*?)\)/;
      if (regExp.test(funcString)) {
        const argList = RegExp.$1.split(',');
        return argList.map(arg => arg.replace(/\s/g, ''));
      } else {
        return [];
      }
    }

    let comp = document.querySelector("builder-fiddle");

    // set the modal menu element
    const $targetEl = document.getElementById('fieldLayoutModal');
    // options with default values
    const options = {
      placement: 'top-center',
      backdrop: 'dynamic',
      backdropClasses:
        'bg-gray-900/50 dark:bg-gray-900/80 fixed inset-0 z-40',
      closable: true,
      onHide: () => {
        console.log('modal is hidden');
      },
      onShow: () => {
        console.log('modal is shown');
      },
      onToggle: () => {
        console.log('modal has been toggled');
      },
    };
    // instance options object
    const instanceOptions = {
      id: 'fieldLayoutModal',
      override: true
    };
    const modal = new Flowbite.default.Modal($targetEl, options, instanceOptions);

    const loadPage = async () => {
      const { assetUrls, rootUrl, userId, tenantId, authToken, id } = settings;

      // 如果传入 steedos rooturl
      if (rootUrl && !authToken) return;

      const initialContent = {
        type: "page",
        title: "Welcome to Steedos",
        body: [],
        regions: ["body"],
        data: {
          context: {
            rootUrl,
            userId,
            tenantId,
            authToken,
          },
          global: {
            userId: userId,
            spaceId: tenantId,
            user: <%- JSON.stringify(userSession) %>, 
            now: new Date(),
          }
        },
      };

      if (id) {
        const result = await axios.post(
          `${rootUrl}/graphql`,
          {
            //forms作为对象
            query: `
                  {
                    record:forms__findOne(id: "${id}"){
                      _id,
                      name,
                      description,
                      amis_schema,
                      current
                    }
                  }
                `
          },
          {
            withCredentials: true,
            headers: { Authorization: `Bearer ${tenantId},${authToken}` },
          }
        );
        if (result?.data?.data?.record) {
          let schema = JSON.parse(result.data.data.record.amis_schema);


          if (!schema) {
            //进if说明schema字段为空 说明为旧表单 对schema重新赋值
            schema = {
              type: 'steedos-flow-form',
              id: "instanceForm",
              name: result.data.data.record.name,
              label: result.data.data.record.name,
              description: result.data.data.record.description,
              className: "steedos-flow-form steedos-flow-layout-page",
              body: []
            }
            if (result.data.data.record.current.fields) {
              for (let i = 0; i < result.data.data.record.current.fields.length; i++) {
                const temp = await getFieldEditTpl(result.data.data.record.current.fields[i]);
                if (temp) {
                  schema.body.push(temp);
                }

              }
            }
          }

          let objectName = result.data.object;
          let pageType = result.data.type;
          if (typeof schema === "string") {
            schema = JSON.parse(schema);
          }

          if (!schema.data) {
            schema.data = {};
          }

          if (!schema.data.context) {
            schema.data.context = {};
          }

          schema.data.app_id = '';
          schema.data.tab_id = '';
          schema.data.object_name = '';
          schema.data.dataComponentId = '';
          schema.data.record_id = '';
          schema.data.record = {};
          schema.data.permissions = {};

          schema.data.context.rootUrl = rootUrl;
          schema.data.context.tenantId = tenantId;
          schema.data.context.userId = userId;
          schema.data.context.authToken = authToken;

          schema.data.global = {
            userId: userId,
            spaceId: tenantId,
            user: <%- JSON.stringify(userSession) %>, 
            now: new Date(),
          }

          return schema || initialContent
        }
      } else {
        return initialContent
      }
    };



    const getSelectOptions = (field) => {
      const options = [];
      // each(field.options.split("\n"), (item) => {
      //   var foo = item.split(":");
      //   if (foo.length == 2) {
      //     options.push({ label: foo[0], value: foo[1] });
      //   } else {
      //     options.push({ label: item, value: item });
      //   }
      // });

      const splitItem = field.options.split("\n");
      splitItem.forEach(item => {
        var foo = item.split(":");
        if (foo.length == 2) {
          options.push({ label: foo[0], value: foo[1] });
        } else {
          options.push({ label: item, value: item });
        }
      });

      return options;
    };

    const startsWith = (url, str) => {

      let flag = false
      if (url.substr(0, 4) === str) {
        flag = true
      } else {
        flag = false
      }
      return flag

    }

    //将原数据字段转换为amis字段
    const getFieldEditTpl = async (field) => {

      if(field.steedos_field){
        return {
          type: `sfield-${_.toLower(_.camelCase(field.steedos_field.type))}`,
          config: field.steedos_field,
          _id: field._id
        }
      }

      // Handle new approval_comments field format from migration
      if(field.type === 'steedos-field' && field.config?.type === 'approval_comments'){
        return {
          type: 'sfield-approvalcomments',
          _id: field._id || field.id,
          label: field.config.label,
          name: field.config.name,
          required: field.is_required || field.required,
          className: (field.is_wide ? 'is_wide' : '') +
            (field.is_list_display ? ' is_list_display' : '') +
            (field.is_searchable ? ' is_searchable' : ''),
          id: field.id,
          config: field.config,
          visibleOn: field.visibleOn,
          requiredOn: field.requiredOn
        };
      }

      const tpl = {
        _id: field._id,
        label: field.name || field.code,
        name: field.code,
        required: field.is_required,
        multiple: field.is_multiselect,
        className: (field.is_wide ? 'is_wide' : '') +
          (field.is_list_display ? ' is_list_display' : '') +
          (field.is_searchable ? ' is_searchable' : '')
      };

      if(field.default_value){
        tpl.value = field.default_value;
      }

      switch (field.type) {
        case "input":
          if (field.is_textarea) {
            tpl.type = "textarea";
          } else {
            tpl.type = "input-text";
          }
          if(field.formula){
            if(field.formula.startsWith('{') && (field.formula.endsWith('}') || field.formula.indexOf("}") > 0)){
              // {申请人姓名}.organization.fullname 转换为 ${申请人姓名.organization.fullname}
              // {申请人姓名.organization.fullname} 转换为 ${申请人姓名.organization.fullname}  
              if(field.formula.indexOf("}.") > 0){
                // {申请人姓名}.organization.fullname
                let formula = field.formula;
                formula = formula.substring(1, formula.indexOf("}"));
                tpl.value = `\${${formula}${field.formula.substring( field.formula.indexOf("}") + 1 )}}`;
              } else {
                // {申请人姓名.organization.fullname}
                tpl.value = `$${field.formula}`;
              }
            }else{
              // 替换掉所有双引号"
              tpl.value = field.formula.replace(/"/g, '');
            }
          }
          break;
        case "number":
          tpl.type = "input-number";
          tpl.precision=field.digits || 0;
          if(field.formula){
            tpl.value = `$${field.formula}`;
          }
          break;
        case "date":
          tpl.type = "input-date";
          tpl.inputFormat = "YYYY-MM-DD";
          tpl.format = 'YYYY-MM-DDT00:00:00.000[Z]';
          break;
        case "dateTime":
          tpl.type = "input-datetime";
          tpl.inputFormat = "YYYY-MM-DD HH:mm";
          tpl.format = 'YYYY-MM-DDTHH:mm:ss.SSSZ';
          break;
        case "checkbox":
          tpl.type = "checkbox";
          break;

        case "email":
          tpl.type = "input-email";
          tpl.validations = {
            isEmail: true,
          };
          break;
        case "url":
          tpl.type = "input-url";
          tpl.validations = {
            isUrl: true,
          };
          break;
        case "password":
          tpl.type = "input-password";
          tpl.showCounter = true;
          break;
        case "select":
          tpl.type = "select";
          tpl.options = getSelectOptions(field);
          break;

        case "user":
          const useTpl = {
            "type": "steedos-field",
            "id": `u:${field.code}`,
            "config": {
              name: field.code,
              label: field.name,
              reference_to: "space_users",
              reference_to_field: 'user',
              multiple: field.is_multiselect,
              type: "lookup"
            },
          }
          // const useTpl = await lookupToAmis(
          // {
          //   name: field.code,
          //   label: field.name,
          //   reference_to: "space_users",
          //   reference_to_field: 'user',
          //   multiple: field.is_multiselect,
          // },
          //   false,
          //   {}
          // );
          Object.assign(tpl, useTpl);
          break;

        case "group":
          const orgTpl = {
            "type": "steedos-field",
            "id": `u:${field.code}`,
            "config": {
              name: field.code,
              label: field.name,
              reference_to: "organizations",
              multiple: field.is_multiselect,
              type: "lookup"
            }
          }

          // const orgTpl = await lookupToAmis(
          // {
          //   name: field.code,
          //   label: field.name,
          //   reference_to: "organizations",
          //   multiple: field.is_multiselect,
          // },
          //   false,
          //   {}
          // );
          Object.assign(tpl, orgTpl);
          break;
        case "radio":
          tpl.type = "radios";
          tpl.options = getSelectOptions(field);
          break;
        case "multiSelect":
          tpl.type = "checkboxes";
          tpl.options = getSelectOptions(field);
          break;
        case "odata":
          const argsName = getArgumentsList(field.filters);
          var labelField = field.formula.substr(1, field.formula.length - 2);
          labelField = labelField.substr(labelField.indexOf(".") + 1);
          // 加入odata标签以示区别 把field-老表单设计器的元素加入
          tpl.type = "select";
          tpl.description = field.description
          tpl.detail_url = field.detail_url
          tpl.filters = field.filters
          tpl.formula = field.formula
          tpl.is_list_display = field.is_list_display
          tpl.is_multiselect = field.is_multiselect
          tpl.is_required = field.is_required
          tpl.is_searchable = field.is_searchable
          tpl.is_wide = field.is_wide
          tpl.search_field = field.search_field
          tpl._id = field._id
          // tpl.labelField = labelField;
          // tpl.valueField = "_value";
          tpl.source = {
            //判断该field.url是否为http开头
            url: field.url,
            method: "get",
            dataType: "json",
            headers: {
              Authorization: "Bearer ${context.tenantId},${context.authToken}",
            },
            adaptor: `
              payload.data = {
                options: _.map(payload.value, (item)=>{
                  const value = item;
                  item["@label"] = item["${labelField}"]
                  delete item['@odata.editLink'];
                  delete item['@odata.etag'];
                  delete item['@odata.id'];
                  return {
                    label: item["@label"],
                    value: value
                  }
                })
              }
              return payload;
            `,
            requestAdaptor: `
              const filters = \`${_.replace(field.filters, /_.pluck/g, '_.map')}\`;
              const url = \`${field.url}\`;
              if(filters){
                console.log('filters', filters);
                const joinKey = url.indexOf('?') > 0 ? '&' : '?';
                if(filters.startsWith('function(') || filters.startsWith('function (')){
                  const argsName = ${JSON.stringify(argsName)};
                  const fun = eval('_fun='+filters);
                  const funArgs = [];
                  for(const item of argsName){
                    funArgs.push(context[item])
                  }
                  api.url = url + joinKey + "$filter=" + fun.apply({}, funArgs)
                }else{
                  api.url = url + joinKey + "$filter=" + filters
                }
              }else{
                api.url = url  
              }
              api.query = {};
              return api;
            `,
            trackExpression: _.join(_.map(argsName, (item)=>{return `\${${item}|json}`}), '-')
          };
          break;
        case "html":
          if (tpl.disabled) {
            tpl.type = 'html';
          } else {
            tpl.type = "input-rich-text";
          }
          break;
        case "table":
          tpl.type = "input-table";
          tpl.addable = field.permission === "editable";
          tpl.editable = tpl.addable;
          tpl.copyable = tpl.addable;
          tpl.columns = [];
          for (const sField of field.fields) {
            if (sField.type != "hidden") {
              sField.permission = field.permission
              const column = await getFieldEditTpl(sField, true);
              tpl.columns.push(column);
            }
          }
          break;
        case "section":
          tpl.type = "steedos-field-group";
          tpl.title = field.name;
          tpl.description = field.description;
          tpl.body = []
          if (field.fields) {
            for (let i = 0; i < field.fields.length; i++) {
              let fieldsItem = await getFieldEditTpl(field.fields[i], true)
              tpl.body.push(fieldsItem)
            }
          }
          break;
        default:
          break;
      }
      return tpl

    }



    const savePage = async (data) => {
      const { rootUrl, userId, tenantId, authToken, id } = settings;

      if (!id) {
        return;
      }

      // 保存schema时,清理context下的认证信息
      const schema = JSON.parse(
        JSON.stringify(data.data.AmisSchema, null, 4)
      );
      if (schema.data && typeof schema.data.context === 'object') {
        delete schema.data.context
        delete schema.data.global
      }

      return await axios.post(
        `${rootUrl}/graphql`,
        {
          query: `
                  mutation{
                    forms__update(id: "${id}", doc: {amis_schema: ${JSON.stringify(JSON.stringify(schema, null, 4))}}){_id}
                  }
                `,
        },
        {
          withCredentials: true,
          headers: { Authorization: `Bearer ${tenantId},${authToken}` },
        }
      )
        .catch(function (error) {
          // handle error
          console.log(error);
        });


      return result;
    };
    window.addEventListener('message', function (event) {
      const { data } = event;
      if (data) {
        if (data.type === 'builder.loaded') {
          comp.messageFrame('builder.EditorPropsChanged', {
            editorProps: JSON.stringify({
              onChange: function (value) {

              },
              onDndAccept: function (event) {
                return true;
              },
              beforeDelete: function (event) {

              },
              onInit: function () {
                // 创建一个新的 style 元素
                var style = document.createElement('style');
                style.type = "text/css";
                style.media = "screen";
                // 将 CSS 样式写入 style 元素
                style.innerHTML = `
                  .ae-RendererList-groupWrap .ae-RendererList-group:nth-child(n+3) {
                      display: none;
                  }
                 .ae-RendererList-groupWrap .ae-RendererList-head:nth-child(n+2) {
                      display: none !important;
                  }
                  .ae-RendererList-tabs-header .antd-Tabs-link:nth-child(n+2) {
                      display: none !important;
                  }
                  .ae-RendererList-groupWrap .ae-RendererList-group.collapse-content .ae-RendererList-item:hover .ae-RendererIcon{
                    display: none !important;
                  }
                  `;

                // 将 style 元素插入到 head 中
                document.head.appendChild(style);
              },
              disableBultinPlugin: false,
              disablePluginList2: function (id, plugin) {
                if (lodash.includes([
                  "FlexPlugin",
                  "GridPlugin",
                  "ContainerPlugin",
                  "Layout_free_container",
                  "Layout_fixed_top",
                  "Layout_fixed",
                  "CollapseGroupPlugin",
                  "PanelPlugin",
                  "TabsPlugin",
                  "SwitchContainerPlugin",
                  "CRUDPlugin",
                  "Table2Plugin",
                  "TableCRUDPlugin",
                  "FormPlugin",
                  "ServicePlugin",
                  // "TextControlPlugin",
                  // "TextareaControlPlugin",
                  // "NumberControlPlugin",
                  // "SelectControlPlugin",
                  // "NestedSelectControlPlugin",
                  // "ChainedSelectControlPlugin",
                  // "DropDownButtonPlugin",
                  // "CheckboxesControlPlugin",
                  // "RadiosControlPlugin",
                  // "CheckboxControlPlugin",
                  // "DateControlPlugin",
                  // "DateRangeControlPlugin",
                  // "FileControlPlugin",
                  // "ImageControlPlugin",
                  // "ExcelControlPlugin",
                  // "TreeControlPlugin",
                  // "TagControlPlugin",
                  // "ListControlPlugin",
                  // "ButtonGroupControlPlugin",
                  // "ButtonToolbarControlPlugin",
                  // "PickerControlPlugin",
                  // "SwitchControlPlugin",
                  // "RangeControlPlugin",
                  // "RateControlPlugin",
                  // "CityControlPlugin",
                  // "TransferPlugin",
                  // "TabsTransferPlugin",
                  // "ColorControlPlugin",
                  // "ConditionBilderPlugin",
                  // "FieldSetControlPlugin",
                  // "ComboControlPlugin",
                  // "InputGroupControlPlugin",
                  // "TableControlPlugin",
                  // "MatrixControlPlugin",
                  // "RichTextControlPlugin",
                  // "DiffEditorControlPlugin",
                  // "CodeEditorControlPlugin",
                  // "SearchBoxPlugin",
                  // "KVControlPlugin",
                  // "RepeatControlPlugin",
                  // "UUIDControlPlugin",
                  // "LocationControlPlugin",
                  // "SubFormControlPlugin",
                  // "HiddenControlPlugin",
                  // "SignaturePlugin",
                  // "StaticControlPlugin",
                  "ButtonPlugin",
                  "ButtonGroupPlugin",
                  "NavPlugin",
                  "AnchorNavPlugin",
                  "TooltipWrapperPlugin",
                  "AlertPlugin",
                  "WizardPlugin",
                  "TableViewPlugin",
                  "WebComponentPlugin",
                  "AudioPlugin",
                  "VideoPlugin",
                  "CustomPlugin",
                  "TasksPlugin",
                  "EachPlugin",
                  "PropertyPlugin",
                  "IFramePlugin",
                  "QRCodePlugin",
                  "TplPlugin",
                  "IconPlugin",
                  "LinkPlugin",
                  "ListPlugin",
                  "List2Plugin",
                  "MappingPlugin",
                  "AvatarPlugin",
                  "CardPlugin",
                  "Card2Plugin",
                  "CardsPlugin",
                  "TablePlugin",
                  "TableCell2Plugin",
                  "ChartPlugin",
                  "SparklinePlugin",
                  "CarouselPlugin",
                  "ImagePlugin",
                  "ImagesPlugin",
                  "DatePlugin",
                  "TimePlugin",
                  "DatetimePlugin",
                  "CalendarPlugin",
                  "TagPlugin",
                  "JsonPlugin",
                  "ProgressPlugin",
                  "StatusPlugin",
                  "StepsPlugin",
                  "TimelinePlugin",
                  // "DividerPlugin",
                  // "CodeViewPlugin",
                  // "MarkdownPlugin",
                  // "CollapsePlugin",
                  "OfficeViewerPlugin",
                  "PdfViewerPlugin",
                  "LogPlugin",
                  "ActionPlugin",
                  "TableCellPlugin",
                  "ArrayControlPlugin",
                  "ControlPlugin",
                  "DateTimeControlPlugin",
                  "DateTimeRangeControlPlugin",
                  "EmailControlPlugin",
                  "FormulaControlPlugin",
                  "GroupControlPlugin",
                  "ItemPlugin",
                  "MonthControlPlugin",
                  "MonthRangeControlPlugin",
                  "PasswordControlPlugin",
                  "InputQuarterPlugin",
                  "QuarterRangePlugin",
                  "TimeControlPlugin",
                  "TimeRangeControlPlugin",
                  "TreeSelectControlPlugin",
                  "URLControlPlugin",
                  "YearControlPlugin",
                  "YearRangeControlPlugin",
                  "BreadcrumbPlugin",
                  "CustomRegionPlugin",
                  "DialogPlugin",
                  "DrawerPlugin",
                  "HBoxPlugin",
                  "ListItemPlugin",
                  "OperationPlugin",
                  // "PagePlugin",
                  "PaginationPlugin",
                  "PlainPlugin",
                  "ResetPlugin",
                  "SubmitPlugin",
                  "WrapperPlugin",
                  "ColumnToggler"
                ]
                  , id)) {
                  return true;
                }
                return false
              }
            }, (key, value) => {
              if (typeof value === 'function') {
                return value.toString();
              }
              return value;
            })
          })
        }
        if (data.type === 'builder.loadContent') {
          loadPage().then((content) => {
            comp.messageFrame('builder.contentChanged', { AmisSchema: content })
          })
        }
        if (data.type === 'builder.saveContent') {
          savePage(data.data).then(() => {
            comp.messageFrame('builder.contentSaved')
          })
        }
      }
    })
    comp.settings = settings;
  </script>
</body>

</html>