Plugin Directory

Changeset 3400645


Ignore:
Timestamp:
11/21/2025 06:12:31 PM (4 months ago)
Author:
trainingbusinesspros
Message:

Update to version 4.2.9 from GitHub

Location:
groundhogg
Files:
2 added
30 edited
1 copied

Legend:

Unmodified
Added
Removed
  • groundhogg/tags/4.2.9/README.txt

    r3395861 r3400645  
    77Tested up to: 6.8
    88Requires PHP: 7.1
    9 Stable tag: 4.2.8
     9Stable tag: 4.2.9
    1010License: GPLv3
    1111License URI: https://www.gnu.org/licenses/gpl.md
     
    378378
    379379== Changelog ==
     380
     381= 4.2.9 (2025-11-21) =
     382* ADDED WP Fusion event tracking filter so you don't **have** to use the custom activity filter.
     383* ADDED "Day of Week" and "Day of Month" filters for conditional logic.
     384* ADDED Email preview action to the broadcasts table and broadcast report.
     385* IMPROVED Recaptcha and Turnstile scripts are now only enqueued if the fields are actually being used.
     386* FIXED Some of the meta-comparisons for the custom activity filter and submission filters not returning correct results.
    380387
    381388= 4.2.8 (2025-11-14) =
  • groundhogg/tags/4.2.9/admin/broadcasts/broadcasts-table.php

    r3394550 r3400645  
    244244        ], $broadcast->is_email() ? esc_html__( 'Edit email', 'groundhogg' ) : esc_html__( 'Edit SMS' , 'groundhogg' ) );
    245245
     246        if ( $broadcast->is_email() ){
     247            $actions[] = html()->a( '#', esc_html__( 'Preview', 'groundhogg' ), [ 'class' => 'gh-email-preview', 'data-id' => $broadcast->get_object_id() ] );
     248        }
     249
    246250        // Add query action
    247251        $query = $broadcast->get_query();
  • groundhogg/tags/4.2.9/admin/emails/emails-table.php

    r3394550 r3400645  
    330330        switch ( $this->get_view() ) {
    331331            default:
     332                $actions[] = [ 'class' => 'edit', 'display' => esc_html__( 'Edit' , 'groundhogg' ), 'url' => $item->admin_link() ];
    332333                $actions[] = [ 'class' => 'gh-email-preview', 'display' => esc_html__( 'Preview' , 'groundhogg' ), 'url' => '#' ];
    333                 $actions[] = [ 'class' => 'edit', 'display' => esc_html__( 'Edit' , 'groundhogg' ), 'url' => $item->admin_link() ];
    334334                $actions[] = [
    335335                    'class'   => 'duplicate',
  • groundhogg/tags/4.2.9/admin/reports/reports-page.php

    r3394550 r3400645  
    141141                wp_enqueue_style( 'baremetrics-calendar' );
    142142                wp_enqueue_script( 'groundhogg-admin-reporting' );
     143                wp_enqueue_script( 'groundhogg-admin-components' );
    143144
    144145                $start = get_request_var( 'start' );
  • groundhogg/tags/4.2.9/admin/reports/views/broadcast-single.php

    r3343709 r3400645  
    1616<div class="display-flex gap-20 align-center">
    1717    <h1 class="report-title"><?php echo esc_html( $broadcast->get_title() ) ?></h1>
     18    <?php if ( $broadcast->is_email() ): ?>
     19        <a href="#" class="gh-button secondary gh-email-preview" data-id="<?php echo esc_attr( $broadcast->get_object_id() ); ?>"><?php esc_html_e( 'Preview', 'groundhogg' ); ?></a>
     20    <?php endif; ?>
    1821</div>
    1922<div class="display-grid gap-20">
  • groundhogg/tags/4.2.9/assets/js/admin/components.js

    r3314835 r3400645  
    17881788
    17891789  $(() => {
    1790     $(document).on('click', 'table.wp-list-table .gh-email-preview', e => {
     1790    $(document).on('click', 'a.gh-email-preview', e => {
    17911791      e.preventDefault()
    17921792
    1793       EmailPreviewModal(parseInt($(e.currentTarget).closest('tr').attr('id')), {})
     1793      let emailId = e.currentTarget.dataset.id ?? e.currentTarget.closest('tr').id
     1794
     1795      EmailPreviewModal(parseInt(emailId), {})
    17941796    })
    17951797  })
  • groundhogg/tags/4.2.9/assets/js/admin/components.min.js

    r3314835 r3400645  
    1 ($=>{const{modal,errorDialog,loadingDots,select,uuid,addMediaToBasicTinyMCE,specialChars,tinymceElement,searchOptionsWidget,input,isNumeric,icons,dialog,tooltip,regexp,isValidEmail,loadingModal,textarea,spinner,skeleton,adminPageURL}=Groundhogg.element;const{Div,H2,H4,Toggle,Img,An,Span,ModalFrame,Iframe,makeEl,Button,Modal,ModalWithHeader,Dashicon,ToolTip,Input,TinyMCE,Label,Fragment,ItemPicker,Skeleton,Pg,Form,Textarea,InputGroup}=MakeEl;const{contacts:ContactsStore,tags:TagsStore,forms:FormsStore,emails:EmailsStore}=Groundhogg.stores;const{post,routes,postFormData}=Groundhogg.api;const{tagPicker}=Groundhogg.pickers;const{userHasCap,getOwner}=Groundhogg.user;const{sprintf,__,_x,_n}=wp.i18n;const{formatDateTime}=Groundhogg.formatting;const{currentUser}=Groundhogg;const{maybeCall,debounce,jsonCopy}=Groundhogg.functions;const selectContactModal=({onSelect:onSelect=()=>{},onClose:onClose=()=>{},exclude:exclude=[]})=>{Modal({dialogClasses:"no-padding",width:"400px",onOpen:e=>{document.getElementById("quick-search-input").focus()}},({close})=>QuickSearch({itemProps:contact=>({onClick:e=>{onSelect(contact);close()}}),queryOverrides:{limit:15,exclude:exclude}}))};const betterTagPicker=(el,{selected:selected=[],removeTags:removeTags=[],addTags:addTags=[],onChange:onChange=changes=>{}})=>{const $el=$(el);let timeout;const template=()=>{return`
     1($=>{const{modal,errorDialog,loadingDots,select,uuid,addMediaToBasicTinyMCE,specialChars,tinymceElement,searchOptionsWidget,input,isNumeric,icons,dialog,tooltip,regexp,isValidEmail,loadingModal,textarea,spinner,skeleton,adminPageURL}=Groundhogg.element;const{Div,H2,H4,Toggle,Img,An,Span,ModalFrame,Iframe,makeEl,Button,Modal,ModalWithHeader,Dashicon,ToolTip,Input,TinyMCE,Label,Fragment,ItemPicker,Skeleton,Pg,Form,Textarea,InputGroup}=MakeEl;const{contacts:ContactsStore,tags:TagsStore,forms:FormsStore,emails:EmailsStore}=Groundhogg.stores;const{post,routes,postFormData}=Groundhogg.api;const{tagPicker}=Groundhogg.pickers;const{userHasCap,getOwner}=Groundhogg.user;const{sprintf,__,_x,_n}=wp.i18n;const{formatDateTime}=Groundhogg.formatting;const{currentUser}=Groundhogg;const{maybeCall,debounce,jsonCopy}=Groundhogg.functions;const selectContactModal=({onSelect=()=>{},onClose=()=>{},exclude=[]})=>{Modal({dialogClasses:"no-padding",width:"400px",onOpen:e=>{document.getElementById("quick-search-input").focus()}},({close})=>QuickSearch({itemProps:contact=>({onClick:e=>{onSelect(contact);close()}}),queryOverrides:{limit:15,exclude:exclude}}))};const betterTagPicker=(el,{selected=[],removeTags=[],addTags=[],onChange=changes=>{}})=>{const $el=$(el);let timeout;const template=()=>{return`
    22          <div class="gh-tags">
    33              ${selected.map(tag=>`<span class="gh-tag${removeTags.includes(tag.ID)?" remove":""}">${tag.data.tag_name} <span data-id="${tag.ID}" class="remove-tag dashicons dashicons-no-alt"></span></span>`).join("")}
     
    66                  <span class="dashicons dashicons-plus-alt2"></span>
    77              </button>
    8           </div>`};const mount=()=>{$el.html(template());onMount()};const informChanges=()=>{onChange({removeTags:removeTags,addTags:addTags})};const onMount=()=>{tooltip($el.find(".add-tag"),{content:__("Add a tag","groundhogg")});$el.find(".gh-tag .remove-tag").on("click",e=>{let tagId=parseInt(e.currentTarget.dataset.id);if(removeTags.includes(tagId)){removeTags.splice(removeTags.indexOf(tagId),1)}else{removeTags.push(tagId)}informChanges();mount()});$el.find(".gh-tag .remove-adding-tag").on("click",e=>{let tagId=parseInt(e.currentTarget.dataset.id);if(addTags.includes(tagId)){addTags.splice(addTags.indexOf(tagId),1)}informChanges();mount()});$el.find(".add-tag").on("click",e=>{const filterTags=tags=>tags.filter(t=>!selected.map(_t=>_t.ID).includes(t.ID)&&!addTags.includes(t.ID)).sort((a,b)=>b.ID-a.ID);let initialOptions=filterTags(TagsStore.getItems());searchOptionsWidget({target:e.currentTarget,position:"fixed",noOptions:__("No tags found...","groundhogg"),options:initialOptions,filterOption:({data},search)=>data.tag_name.match(regexp(search)),filterOptions:(opts,search)=>{if(!search){return opts}if(userHasCap("add_tags")){opts.unshift({ID:search,data:{tag_name:sprintf(__('Add "%s"',"groundhogg"),search)}})}return opts},renderOption:({data})=>data.tag_name,onClose:()=>{mount()},onInput:(search,widget)=>{if(timeout){clearTimeout(timeout)}timeout=setTimeout(()=>{TagsStore.fetchItems({search:search}).then(()=>{widget.options=filterTags(TagsStore.getItems());widget.mountOptions()})},1500)},onSelect:tag=>{let{ID}=tag;if(!isNumeric(ID)){TagsStore.post({data:{tag_name:ID}}).then(t=>{addTags.push(t.ID);informChanges();mount()});return}addTags.push(ID);informChanges()},onOpen:widget=>{if(!initialOptions.length){TagsStore.fetchItems().then(()=>{widget.options=filterTags(TagsStore.getItems());widget.mountOptions()})}}}).mount()})};TagsStore.itemsFetched(selected);mount()};const quickEditContactModal=({contact,prefix:prefix="quick-edit",onEdit:onEdit=contact=>{},additionalFields:additionalFields=()=>"",additionalFieldsOnMount:additionalFieldsOnMount=()=>{}})=>{if(contact&&contact.tags){TagsStore.itemsFetched(contact.tags)}const getContact=()=>{return ContactsStore.get(contact.ID)};const quickEdit=contact=>{return`
     8          </div>`};const mount=()=>{$el.html(template());onMount()};const informChanges=()=>{onChange({removeTags:removeTags,addTags:addTags})};const onMount=()=>{tooltip($el.find(".add-tag"),{content:__("Add a tag","groundhogg")});$el.find(".gh-tag .remove-tag").on("click",e=>{let tagId=parseInt(e.currentTarget.dataset.id);if(removeTags.includes(tagId)){removeTags.splice(removeTags.indexOf(tagId),1)}else{removeTags.push(tagId)}informChanges();mount()});$el.find(".gh-tag .remove-adding-tag").on("click",e=>{let tagId=parseInt(e.currentTarget.dataset.id);if(addTags.includes(tagId)){addTags.splice(addTags.indexOf(tagId),1)}informChanges();mount()});$el.find(".add-tag").on("click",e=>{const filterTags=tags=>tags.filter(t=>!selected.map(_t=>_t.ID).includes(t.ID)&&!addTags.includes(t.ID)).sort((a,b)=>b.ID-a.ID);let initialOptions=filterTags(TagsStore.getItems());searchOptionsWidget({target:e.currentTarget,position:"fixed",noOptions:__("No tags found...","groundhogg"),options:initialOptions,filterOption:({data},search)=>data.tag_name.match(regexp(search)),filterOptions:(opts,search)=>{if(!search){return opts}if(userHasCap("add_tags")){opts.unshift({ID:search,data:{tag_name:sprintf(__('Add "%s"',"groundhogg"),search)}})}return opts},renderOption:({data})=>data.tag_name,onClose:()=>{mount()},onInput:(search,widget)=>{if(timeout){clearTimeout(timeout)}timeout=setTimeout(()=>{TagsStore.fetchItems({search:search}).then(()=>{widget.options=filterTags(TagsStore.getItems());widget.mountOptions()})},1500)},onSelect:tag=>{let{ID}=tag;if(!isNumeric(ID)){TagsStore.post({data:{tag_name:ID}}).then(t=>{addTags.push(t.ID);informChanges();mount()});return}addTags.push(ID);informChanges()},onOpen:widget=>{if(!initialOptions.length){TagsStore.fetchItems().then(()=>{widget.options=filterTags(TagsStore.getItems());widget.mountOptions()})}}}).mount()})};TagsStore.itemsFetched(selected);mount()};const quickEditContactModal=({contact,prefix="quick-edit",onEdit=contact=>{},additionalFields=()=>"",additionalFieldsOnMount=()=>{}})=>{if(contact&&contact.tags){TagsStore.itemsFetched(contact.tags)}const getContact=()=>{return ContactsStore.get(contact.ID)};const quickEdit=contact=>{return`
    99          <div class="contact-quick-edit" tabindex="0">
    1010              <div class="gh-header space-between">
     
    8080                  <button class="gh-button primary" id="${prefix}-save">${__("Save Changes","groundhogg")}</button>
    8181              </div>
    82           </div>`};const quickEditMounted=({close,setContent})=>{let payload;const clearPayload=()=>{payload={data:{},meta:{},add_tags:[],remove_tags:[]}};clearPayload();const updateContact=data=>{payload={...data,data:{...payload.data,...data.data},meta:{...payload.meta,...data.meta}}};const $quickEdit=$(".contact-quick-edit");$quickEdit.focus();$(`#${prefix}-save`).on("click",e=>{const $btn=$(e.target);$btn.prop("disabled",true);$btn.text(__("Saving","groundhogg"));const{stop}=loadingDots(`#${prefix}-save`);ContactsStore.patch(contact.ID,payload).then(c=>{stop();clearPayload();onEdit(c);setContent(quickEdit(getContact()));quickEditMounted({close:close,setContent:setContent})}).catch(e=>{stop();clearPayload();setContent(quickEdit(getContact()));quickEditMounted({close:close,setContent:setContent});console.log(e);dialog({type:"error",message:e.message})})});$(`.${prefix}-cancel`).on("click",e=>{clearPayload();close()});betterTagPicker(`#${prefix}-tags-here`,{selected:getContact().tags,onChange:({addTags,removeTags})=>{updateContact({add_tags:addTags,remove_tags:removeTags})}});$(`#${prefix}-first-name, #${prefix}-last-name, #${prefix}-email, #${prefix}-optin-status, #${prefix}-owner`).on("change",e=>{updateContact({data:{[e.target.name]:e.target.value}})});$(`#${prefix}-primary-phone, #${prefix}-primary-phone-extension, #${prefix}-mobile-phone`).on("change",e=>{updateContact({meta:{[e.target.name]:e.target.value}})});additionalFieldsOnMount({prefix:prefix,contact:contact,setPayload:updateContact,getPayload:()=>payload})};const{close,setContent}=modal({content:quickEdit(getContact()),onOpen:quickEditMounted})};const quickAddForm=(selector,{prefix:prefix="quick-add",onCreate:onCreate=()=>{},additionalFields:additionalFields=({prefix})=>"",additionalFieldsOnMount:additionalFieldsOnMount=()=>{}})=>{const quickAddForm=()=>{return`
     82          </div>`};const quickEditMounted=({close,setContent})=>{let payload;const clearPayload=()=>{payload={data:{},meta:{},add_tags:[],remove_tags:[]}};clearPayload();const updateContact=data=>{payload={...data,data:{...payload.data,...data.data},meta:{...payload.meta,...data.meta}}};const $quickEdit=$(".contact-quick-edit");$quickEdit.focus();$(`#${prefix}-save`).on("click",e=>{const $btn=$(e.target);$btn.prop("disabled",true);$btn.text(__("Saving","groundhogg"));const{stop}=loadingDots(`#${prefix}-save`);ContactsStore.patch(contact.ID,payload).then(c=>{stop();clearPayload();onEdit(c);setContent(quickEdit(getContact()));quickEditMounted({close:close,setContent:setContent})}).catch(e=>{stop();clearPayload();setContent(quickEdit(getContact()));quickEditMounted({close:close,setContent:setContent});console.log(e);dialog({type:"error",message:e.message})})});$(`.${prefix}-cancel`).on("click",e=>{clearPayload();close()});betterTagPicker(`#${prefix}-tags-here`,{selected:getContact().tags,onChange:({addTags,removeTags})=>{updateContact({add_tags:addTags,remove_tags:removeTags})}});$(`#${prefix}-first-name, #${prefix}-last-name, #${prefix}-email, #${prefix}-optin-status, #${prefix}-owner`).on("change",e=>{updateContact({data:{[e.target.name]:e.target.value}})});$(`#${prefix}-primary-phone, #${prefix}-primary-phone-extension, #${prefix}-mobile-phone`).on("change",e=>{updateContact({meta:{[e.target.name]:e.target.value}})});additionalFieldsOnMount({prefix:prefix,contact:contact,setPayload:updateContact,getPayload:()=>payload})};const{close,setContent}=modal({content:quickEdit(getContact()),onOpen:quickEditMounted})};const quickAddForm=(selector,{prefix="quick-add",onCreate=()=>{},additionalFields=({prefix})=>"",additionalFieldsOnMount=()=>{}})=>{const quickAddForm=()=>{return`
    8383          <div class="gh-rows-and-columns">
    8484              <div class="gh-row">
     
    170170    #${prefix}-terms,
    171171    #${prefix}-data-consent,
    172     #${prefix}-marketing-consent`).on("change",({target})=>{setPayload({meta:{..._payload.meta,[target.name]:target.checked}})});betterTagPicker(`   #${prefix}-tags-here`,{selected:[],onChange:({addTags})=>{setPayload({tags:addTags})}});additionalFieldsOnMount({prefix:prefix,setPayload:setPayload,getPayload:getPayload})};const internalForm=({contact:contact=false,onSubmit:onSubmit=()=>{}})=>{let selectedForm;const ui=()=>{return`
     172    #${prefix}-marketing-consent`).on("change",({target})=>{setPayload({meta:{..._payload.meta,[target.name]:target.checked}})});betterTagPicker(`   #${prefix}-tags-here`,{selected:[],onChange:({addTags})=>{setPayload({tags:addTags})}});additionalFieldsOnMount({prefix:prefix,setPayload:setPayload,getPayload:getPayload})};const internalForm=({contact=false,onSubmit=()=>{}})=>{let selectedForm;const ui=()=>{return`
    173173          <div class="gh-header">
    174174              <div class="display-flex gap-20 full-width">
     
    180180          <div class="form-wrap">
    181181              ${selectedForm?selectedForm.rendered:`<p>${__("Select a form using the dropdown","groundhogg")}</p>`}
    182           </div>`};return modal({width:500,content:ui(),dialogClasses:"internal-form-wrap",onOpen:({setContent,close})=>{const reMount=()=>{setContent(ui());onMount()};const onMount=()=>{$("#cancel").on("click",()=>close());$(`#select-form`).ghPicker({endpoint:FormsStore.route,width:"100%",placeholder:__("Type to select a form...","groundhogg"),data:[{id:"",text:""},...FormsStore.getItems().map(f=>({id:f.ID,text:f.name,selected:selectedForm&&f.ID==selectedForm.ID}))],getParams:q=>({...q,search:q.term,active:true,contact:contact.ID}),getResults:({items})=>{FormsStore.itemsFetched(items);return items.map(f=>({id:f.ID,text:f.name}))}}).on("select2:select",e=>{selectedForm=FormsStore.get(e.params.data.id);reMount()});if(selectedForm){$(".internal-form-wrap form.gh-form").on("submit",e=>{e.preventDefault();const $form=$(e.currentTarget);handleInternalFormSubmit(selectedForm.ID,$form,c=>{close();onSubmit(c)})})}};onMount()}})};const handleInternalFormSubmit=(formId,$form,onSubmit)=>{let $btn=$form.find(".gh-submit");let origTxt=$btn.text();$btn.prop("disabled",true);$btn.text(__("Submitting","groundhogg"));const{stop}=loadingDots($btn);var data=new FormData($form[0]);if($form.is(".gh-form-v2")){postFormData(`${FormsStore.route}/${formId}/admin`,data).then(r=>{$btn.prop("disabled",false);$btn.text(origTxt);if(r.status&&r.status==="success"){dialog({message:__("Form submitted!")});ContactsStore.itemsFetched([r.contact]);onSubmit(r.contact);return}dialog({message:r.additional_errors[0].message,type:"error"})})}else{data.append("action","groundhogg_ajax_form_submit");$.ajax({method:"POST",url:ajaxurl,data:data,processData:false,contentType:false,cache:false,timeout:6e5,enctype:"multipart/form-data",success:r=>{stop();$btn.prop("disabled",false);$btn.text(origTxt);if(!r.success){dialog({message:r.data[0].message,type:"error"})}else{dialog({message:__("Form submitted!")});ContactsStore.itemsFetched([r.data.contact]);onSubmit(r.data.contact)}},error:e=>{dialog({message:__("Something went wrong...","groundhogg"),type:"error"})}})}};const addContactModal=({prefix:prefix="quick-add",onCreate:onCreate=()=>{},additionalFields:additionalFields=()=>"",additionalFieldsOnMount:additionalFieldsOnMount=()=>{}})=>{let method="quick-add";let selectedForm;const form=()=>{const quickAddForm=()=>{return`
     182          </div>`};return modal({width:500,content:ui(),dialogClasses:"internal-form-wrap",onOpen:({setContent,close})=>{const reMount=()=>{setContent(ui());onMount()};const onMount=()=>{$("#cancel").on("click",()=>close());$(`#select-form`).ghPicker({endpoint:FormsStore.route,width:"100%",placeholder:__("Type to select a form...","groundhogg"),data:[{id:"",text:""},...FormsStore.getItems().map(f=>({id:f.ID,text:f.name,selected:selectedForm&&f.ID==selectedForm.ID}))],getParams:q=>({...q,search:q.term,active:true,contact:contact.ID}),getResults:({items})=>{FormsStore.itemsFetched(items);return items.map(f=>({id:f.ID,text:f.name}))}}).on("select2:select",e=>{selectedForm=FormsStore.get(e.params.data.id);reMount()});if(selectedForm){$(".internal-form-wrap form.gh-form").on("submit",e=>{e.preventDefault();const $form=$(e.currentTarget);handleInternalFormSubmit(selectedForm.ID,$form,c=>{close();onSubmit(c)})})}};onMount()}})};const handleInternalFormSubmit=(formId,$form,onSubmit)=>{let $btn=$form.find(".gh-submit");let origTxt=$btn.text();$btn.prop("disabled",true);$btn.text(__("Submitting","groundhogg"));const{stop}=loadingDots($btn);var data=new FormData($form[0]);if($form.is(".gh-form-v2")){postFormData(`${FormsStore.route}/${formId}/admin`,data).then(r=>{$btn.prop("disabled",false);$btn.text(origTxt);if(r.status&&r.status==="success"){dialog({message:__("Form submitted!")});ContactsStore.itemsFetched([r.contact]);onSubmit(r.contact);return}dialog({message:r.additional_errors[0].message,type:"error"})})}else{data.append("action","groundhogg_ajax_form_submit");$.ajax({method:"POST",url:ajaxurl,data:data,processData:false,contentType:false,cache:false,timeout:6e5,enctype:"multipart/form-data",success:r=>{stop();$btn.prop("disabled",false);$btn.text(origTxt);if(!r.success){dialog({message:r.data[0].message,type:"error"})}else{dialog({message:__("Form submitted!")});ContactsStore.itemsFetched([r.data.contact]);onSubmit(r.data.contact)}},error:e=>{dialog({message:__("Something went wrong...","groundhogg"),type:"error"})}})}};const addContactModal=({prefix="quick-add",onCreate=()=>{},additionalFields=()=>"",additionalFieldsOnMount=()=>{}})=>{let method="quick-add";let selectedForm;const form=()=>{const quickAddForm=()=>{return`
    183183            <div id="${prefix}-quick-add-form"></div>`};const useForm=()=>{return`
    184184            <div class="gh-rows-and-columns">
     
    208208              ${method=="form"?useForm():quickAddForm()}
    209209          </div>
    210       `};const onMount=({close,setContent})=>{const reMount=()=>{setContent(form());onMount({close:close,setContent:setContent})};tooltip(".use-quick-add",{content:__("Use quick-add form","groundhogg")});tooltip(".use-form",{content:__("Use internal form","groundhogg")});$(".use-form").on("click",e=>{method="form";reMount()});$(".use-quick-add").on("click",e=>{method="quick-add";reMount()});$(`.${prefix}-cancel`).on("click",close);if(method=="quick-add"){quickAddForm(`#${prefix}-quick-add-form`,{prefix:prefix,additionalFields:additionalFields,additionalFieldsOnMount:additionalFieldsOnMount,onCreate:c=>{close();onCreate(c)}})}else{$(`#${prefix}-select-form`).ghPicker({endpoint:FormsStore.route,width:"100%",placeholder:__("Type to search...","groundhogg"),data:[{id:"",text:""},...FormsStore.getItems().map(f=>({id:f.ID,text:f.name,selected:selectedForm&&f.ID==selectedForm.ID}))],getParams:q=>({...q,search:q.term,active:true}),getResults:({items})=>{FormsStore.itemsFetched(items);return items.map(f=>({id:f.ID,text:f.name}))}}).on("select2:select",e=>{selectedForm=FormsStore.get(e.params.data.id);reMount()});if(selectedForm){$(".quick-add-wrap form.gh-form").on("submit",e=>{e.preventDefault();var $form=$(e.currentTarget);handleInternalFormSubmit(selectedForm.ID,$form,c=>{close();onCreate(c)})})}}};return modal({content:form(),onOpen:onMount})};const EmailModal=(props,onSend=()=>{})=>{const State=Groundhogg.createState({to:[],from_user:currentUser.ID,from_name:currentUser.data.display_name,from_email:currentUser.data.user_email,cc:[],showCC:false,bcc:[],showBCC:false,subject:"",content:"",sending:false,...props});const EmailAddressPicker=({label:label="",key:key=""})=>ItemPicker({id:`composed-${key}`,label:`${label}:`,style:{flexGrow:1},noneSelected:`${label}...`,tags:true,selected:State[key].map(v=>({id:v,text:v})),fetchOptions:search=>ContactsStore.fetchItems({search:search}).then(items=>items.map(item=>({id:item.data.email,text:item.data.email}))),isValidSelection:isValidEmail,onChange:items=>State.set({[key]:items.map(item=>item.id)})});return Modal({className:"send-email",dialogClasses:"gh-panel",overlay:false,onClose:()=>{wp.editor.remove("composed-content")}},({close,morph:realMorph})=>{const morph=()=>realMorph({});return Form({id:"compose-email-form",className:"display-flex column gap-10",onSubmit:e=>{e.preventDefault();const{to,from_email,from_name,cc,bcc,subject,content}=State;if(!content){errorDialog({message:"Please add a message."});return false}if(!to.length){errorDialog({message:"Please add a least one recipient."});return false}State.set({sending:true});morph();post(`${routes.v4.emails}/send`,{to:to,from_email:from_email,from_name:from_name,cc:cc,bcc:bcc,subject:subject,content:content}).then(r=>{if(r.status!=="success"){dialog({message:r.message,type:"error"});return}dialog({message:__("Message sent!","groundhogg")});onSend({...r,email:{to:to,from_email:from_email,from_name:from_name,cc:cc,bcc:bcc,subject:subject,content:content}});close()}).catch(e=>{dialog({message:e.message,type:"error"});State.set({sending:false});morph()});return false}},[OwnerPicker({label:"From:",id:"composed-from",selected:[State.from_user],multiple:false,allow0:false,itemDisplay:u=>`${u.data.display_name} &lt;${u.data.user_email}&gt;`,onChange:item=>{State.set({form_user:item.id,from_email:getOwner(item.id).data.user_email,from_name:getOwner(item.id).data.display_name})}}),Div({className:"display-flex gap-5 align-center"},[EmailAddressPicker({label:"To",key:"to"}),State.cc.length||State.showCC?null:An({id:"show-cc",onClick:e=>{State.set({showCC:true});morph()}},"CC"),State.bcc.length||State.showBCC?null:An({id:"show-bcc",onClick:e=>{State.set({showBCC:true});morph()}},"BCC")]),State.cc.length||State.showCC?EmailAddressPicker({label:"CC",key:"cc"}):null,State.bcc.length||State.showBCC?EmailAddressPicker({label:"BCC",key:"bcc"}):null,Input({id:"composed-subject-line",name:"composed_subject_line",required:true,placeholder:__("Subject line..."),value:State.subject,onInput:e=>State.set({subject:e.target.value})}),TinyMCE({id:"composed-content",value:State.content,config:{replacements:true,savedReplies:true,media:true,quicktags:false,tinymce:{height:300}},onChange:content=>State.set({content:content})}),Div({className:"display-flex gap-5 flex-end"},[Button({className:"gh-button danger text",disabled:State.sending,onClick:e=>close()},__("Discard")),Button({type:"submit",className:"gh-button primary",disabled:State.sending},State.sending?Span({className:"gh-spinner"}):__("Send"))])])})};const emailModal=(props,onSend=()=>{})=>{return EmailModal(props,onSend)};const EmailTemplateModal=async(contactId,onSend=()=>{})=>{let contactIds,title;if(Array.isArray(contactId)){contactIds=contactId;title=sprintf(__("Select an email to send to %s contacts","groundhogg"),contactIds.length)}else if(typeof contactId==="object"){let contact=contactId;contactIds=[contact.ID];title=sprintf(__("Select an email to send to %s","groundhogg"),contact.data.full_name.trim()||contact.data.email)}else{let contact=await Groundhogg.stores.contacts.maybeFetchItem(contactId);contactIds=[contact.ID];title=sprintf(__("Select an email to send to %s","groundhogg"),contact.data.full_name.trim()||contact.data.email)}const State=Groundhogg.createState({email:null});MakeEl.Modal({},({morph,close})=>MakeEl.Div({id:"send-email-dialog"},[`<h3>${title}</h3>`,MakeEl.ItemPicker({id:`select-email`,noneSelected:__("Select an email to send...","groundhogg"),selected:State.email?{id:State.email.ID,text:State.email.data.title}:[],multiple:false,style:{flexGrow:1},fetchOptions:search=>{return EmailsStore.fetchItems({search:search,status:"ready"}).then(emails=>emails.map(({ID,data})=>({id:ID,text:data.title})))},onChange:item=>{if(!item){State.set({email:null})}else{let email=EmailsStore.get(item.id);State.set({email:email})}morph()}}),State.email?MakeEl.Div({className:"gh-panel outlined"},Groundhogg.components.EmailPreview({...State.email.context,content:State.email.context.built})):null,State.email?MakeEl.Button({id:"send-email",className:"gh-button primary medium",onClick:e=>{e.currentTarget.disabled=true;e.currentTarget.innerHTML=`<span class="gh-spinner"></span>`;EmailsStore.send(State.email.ID,{to:contactIds}).then(r=>{dialog({message:__("Email sent!")});close();onSend(r)}).catch(e=>{dialog({type:"error",message:e.message});morph()})}},__("Send email now!","groundhogg")):null]))};const makeInput=(selector,{inputProps:inputProps={},value:value="",onChange:onChange=()=>{},replaceWith:replaceWith=()=>{}})=>{inputProps={id:uuid(),value:value,...inputProps};$(selector).replaceWith(input(inputProps));$(`#${inputProps.id}`).focus().on("blur keydown",e=>{if(e.type==="keydown"&&e.key!=="Enter"){return}value=e.target.value;onChange(value);$(`#${inputProps.id}`).replaceWith(replaceWith(value))})};const fileUploader=({action:action="",nonce:nonce="",accept:accept="",multiple:multiple=true,fileName:fileName="file-upload",beforeUpload:beforeUpload=()=>{},onUpload:onUpload=()=>{}})=>{return modal({width:600,dialogClasses:"gh-media-uploader",content:`
     210      `};const onMount=({close,setContent})=>{const reMount=()=>{setContent(form());onMount({close:close,setContent:setContent})};tooltip(".use-quick-add",{content:__("Use quick-add form","groundhogg")});tooltip(".use-form",{content:__("Use internal form","groundhogg")});$(".use-form").on("click",e=>{method="form";reMount()});$(".use-quick-add").on("click",e=>{method="quick-add";reMount()});$(`.${prefix}-cancel`).on("click",close);if(method=="quick-add"){quickAddForm(`#${prefix}-quick-add-form`,{prefix:prefix,additionalFields:additionalFields,additionalFieldsOnMount:additionalFieldsOnMount,onCreate:c=>{close();onCreate(c)}})}else{$(`#${prefix}-select-form`).ghPicker({endpoint:FormsStore.route,width:"100%",placeholder:__("Type to search...","groundhogg"),data:[{id:"",text:""},...FormsStore.getItems().map(f=>({id:f.ID,text:f.name,selected:selectedForm&&f.ID==selectedForm.ID}))],getParams:q=>({...q,search:q.term,active:true}),getResults:({items})=>{FormsStore.itemsFetched(items);return items.map(f=>({id:f.ID,text:f.name}))}}).on("select2:select",e=>{selectedForm=FormsStore.get(e.params.data.id);reMount()});if(selectedForm){$(".quick-add-wrap form.gh-form").on("submit",e=>{e.preventDefault();var $form=$(e.currentTarget);handleInternalFormSubmit(selectedForm.ID,$form,c=>{close();onCreate(c)})})}}};return modal({content:form(),onOpen:onMount})};const EmailModal=(props,onSend=()=>{})=>{const State=Groundhogg.createState({to:[],from_user:currentUser.ID,from_name:currentUser.data.display_name,from_email:currentUser.data.user_email,cc:[],showCC:false,bcc:[],showBCC:false,subject:"",content:"",sending:false,...props});const EmailAddressPicker=({label="",key=""})=>ItemPicker({id:`composed-${key}`,label:`${label}:`,style:{flexGrow:1},noneSelected:`${label}...`,tags:true,selected:State[key].map(v=>({id:v,text:v})),fetchOptions:search=>ContactsStore.fetchItems({search:search}).then(items=>items.map(item=>({id:item.data.email,text:item.data.email}))),isValidSelection:isValidEmail,onChange:items=>State.set({[key]:items.map(item=>item.id)})});return Modal({className:"send-email",dialogClasses:"gh-panel",overlay:false,onClose:()=>{wp.editor.remove("composed-content")}},({close,morph:realMorph})=>{const morph=()=>realMorph({});return Form({id:"compose-email-form",className:"display-flex column gap-10",onSubmit:e=>{e.preventDefault();const{to,from_email,from_name,cc,bcc,subject,content}=State;if(!content){errorDialog({message:"Please add a message."});return false}if(!to.length){errorDialog({message:"Please add a least one recipient."});return false}State.set({sending:true});morph();post(`${routes.v4.emails}/send`,{to:to,from_email:from_email,from_name:from_name,cc:cc,bcc:bcc,subject:subject,content:content}).then(r=>{if(r.status!=="success"){dialog({message:r.message,type:"error"});return}dialog({message:__("Message sent!","groundhogg")});onSend({...r,email:{to:to,from_email:from_email,from_name:from_name,cc:cc,bcc:bcc,subject:subject,content:content}});close()}).catch(e=>{dialog({message:e.message,type:"error"});State.set({sending:false});morph()});return false}},[OwnerPicker({label:"From:",id:"composed-from",selected:[State.from_user],multiple:false,allow0:false,itemDisplay:u=>`${u.data.display_name} &lt;${u.data.user_email}&gt;`,onChange:item=>{State.set({form_user:item.id,from_email:getOwner(item.id).data.user_email,from_name:getOwner(item.id).data.display_name})}}),Div({className:"display-flex gap-5 align-center"},[EmailAddressPicker({label:"To",key:"to"}),State.cc.length||State.showCC?null:An({id:"show-cc",onClick:e=>{State.set({showCC:true});morph()}},"CC"),State.bcc.length||State.showBCC?null:An({id:"show-bcc",onClick:e=>{State.set({showBCC:true});morph()}},"BCC")]),State.cc.length||State.showCC?EmailAddressPicker({label:"CC",key:"cc"}):null,State.bcc.length||State.showBCC?EmailAddressPicker({label:"BCC",key:"bcc"}):null,Input({id:"composed-subject-line",name:"composed_subject_line",required:true,placeholder:__("Subject line..."),value:State.subject,onInput:e=>State.set({subject:e.target.value})}),TinyMCE({id:"composed-content",value:State.content,config:{replacements:true,savedReplies:true,media:true,quicktags:false,tinymce:{height:300}},onChange:content=>State.set({content:content})}),Div({className:"display-flex gap-5 flex-end"},[Button({className:"gh-button danger text",disabled:State.sending,onClick:e=>close()},__("Discard")),Button({type:"submit",className:"gh-button primary",disabled:State.sending},State.sending?Span({className:"gh-spinner"}):__("Send"))])])})};const emailModal=(props,onSend=()=>{})=>{return EmailModal(props,onSend)};const EmailTemplateModal=async(contactId,onSend=()=>{})=>{let contactIds,title;if(Array.isArray(contactId)){contactIds=contactId;title=sprintf(__("Select an email to send to %s contacts","groundhogg"),contactIds.length)}else if(typeof contactId==="object"){let contact=contactId;contactIds=[contact.ID];title=sprintf(__("Select an email to send to %s","groundhogg"),contact.data.full_name.trim()||contact.data.email)}else{let contact=await Groundhogg.stores.contacts.maybeFetchItem(contactId);contactIds=[contact.ID];title=sprintf(__("Select an email to send to %s","groundhogg"),contact.data.full_name.trim()||contact.data.email)}const State=Groundhogg.createState({email:null});MakeEl.Modal({},({morph,close})=>MakeEl.Div({id:"send-email-dialog"},[`<h3>${title}</h3>`,MakeEl.ItemPicker({id:`select-email`,noneSelected:__("Select an email to send...","groundhogg"),selected:State.email?{id:State.email.ID,text:State.email.data.title}:[],multiple:false,style:{flexGrow:1},fetchOptions:search=>{return EmailsStore.fetchItems({search:search,status:"ready"}).then(emails=>emails.map(({ID,data})=>({id:ID,text:data.title})))},onChange:item=>{if(!item){State.set({email:null})}else{let email=EmailsStore.get(item.id);State.set({email:email})}morph()}}),State.email?MakeEl.Div({className:"gh-panel outlined"},Groundhogg.components.EmailPreview({...State.email.context,content:State.email.context.built})):null,State.email?MakeEl.Button({id:"send-email",className:"gh-button primary medium",onClick:e=>{e.currentTarget.disabled=true;e.currentTarget.innerHTML=`<span class="gh-spinner"></span>`;EmailsStore.send(State.email.ID,{to:contactIds}).then(r=>{dialog({message:__("Email sent!")});close();onSend(r)}).catch(e=>{dialog({type:"error",message:e.message});morph()})}},__("Send email now!","groundhogg")):null]))};const makeInput=(selector,{inputProps={},value="",onChange=()=>{},replaceWith=()=>{}})=>{inputProps={id:uuid(),value:value,...inputProps};$(selector).replaceWith(input(inputProps));$(`#${inputProps.id}`).focus().on("blur keydown",e=>{if(e.type==="keydown"&&e.key!=="Enter"){return}value=e.target.value;onChange(value);$(`#${inputProps.id}`).replaceWith(replaceWith(value))})};const fileUploader=({action="",nonce="",accept="",multiple=true,fileName="file-upload",beforeUpload=()=>{},onUpload=()=>{}})=>{return modal({width:600,dialogClasses:"gh-media-uploader",content:`
    211211          ${input({type:"file",id:"upload-file-input",name:"files"+(multiple?"[]":""),className:"hidden",accept:accept,multiple:multiple})}
    212212          <div class="droppable-handler">
     
    216216      <div id="uploading-files"></div>
    217217      <div id="uploaded-files"></div>
    218       `,onOpen:({close})=>{let file=null;let filesToUpload=[];let filesUploaded=[];let uploading=false;const pushFiles=()=>{renderUploadingFiles();file=filesToUpload.pop();if(!file){uploading=false;return}uploading=true;let fd=new FormData;fd.append(fileName,file,file.name);fd.append("gh_admin_ajax_nonce",Groundhogg.nonces._adminajax);fd.append("action",action);beforeUpload(fd);setTimeout(()=>{fetch(ajaxurl,{method:"POST",credentials:"same-origin",body:fd}).then(r=>{if(!r.ok){dialog({message:__("Something when wrong..."),type:"error"});return}return r.json()}).then(r=>{if(!r.success){dialog({message:r.data[0].message,type:"error"});pushFiles();return}onUpload(r,file);filesUploaded.unshift(file);renderUploadedFiles();pushFiles()})},2e3)};const renderUploadingFiles=()=>{$("#uploading-files").html(filesToUpload.map(f=>`<div class="file"><span class="hourglass">⌛</span> ${f.name}</div>`))};const renderUploadedFiles=()=>{$("#uploaded-files").html(filesUploaded.map(f=>`<div class="file">✅ ${f.name}</div>`))};const addFiles=files=>{filesToUpload.push(...files);if(!uploading){pushFiles()}};const $input=$("#upload-file-input");$input.on("change",e=>{addFiles(e.target.files)});$("#select-files").on("click",e=>{e.preventDefault();$input.click()});const $droppable=$(".droppable-handler");$droppable.on("dragover",e=>{e.preventDefault();$droppable.addClass("dragover")}).on("dragleave",e=>{$droppable.removeClass("dragover")}).on("drop",e=>{e.preventDefault();$droppable.removeClass("dragover");let{dataTransfer}=e.originalEvent;addFiles(dataTransfer.files)})}})};const EmailPreviewModal=async(emailId,{height:height=window.innerHeight*.85,width:width=900})=>{const{close}=loadingModal();let email;try{email=await EmailsStore.maybeFetchItem(emailId)}catch(err){close();throw err}const{from_avatar,from_email,from_name,subject,built:content}=email.context;close();return ModalFrame({frameAttributes:{className:"gh-modal-frame gh-email-preview-modal"}},({close})=>Div({style:{width:`${width}px`,height:`${height}px`}},EmailPreview({close:close,from_avatar:from_avatar,from_email:from_email,from_name:from_name,subject:subject,content:content})))};const EmailPreview=({close:close=false,from_avatar,from_email,from_name,subject,content})=>{return Div({className:"email-preview"},[Div({className:"from-preview display-flex gap-20 has-box-shadow"},[makeEl("img",{src:from_avatar,className:"from-avatar",height:40,width:40,style:{borderRadius:"50%"}}),Div({className:"subject-and-from"},[`<h2>${subject}</h2>`,`<span class="from-name">${from_name}</span> <span class="from-email">&lt;${from_email}&gt;</span>`]),close!==false?Button({className:"gh-button secondary icon text",style:{marginLeft:"auto"},onClick:close},Dashicon("no-alt")):null]),Iframe({id:"desktop-preview-iframe"},content)])};$(()=>{$(document).on("click","table.wp-list-table .gh-email-preview",e=>{e.preventDefault();EmailPreviewModal(parseInt($(e.currentTarget).closest("tr").attr("id")),{})})});const ImagePicker=({multiple:multiple=false,title:title=__("Select a image to upload"),selectText:selectText=__("Use this image"),onChange:onChange=attachment=>{}})=>{let file_frame=wp.media({title:title,button:{text:selectText},multiple:multiple});file_frame.on("select",function(){let attachment=file_frame.state().get("selection").first().toJSON();onChange(attachment)});file_frame.open()};const ImageInput=({id,name:name="src",onChange,value:value=""})=>{const handleChange=(value,attachment=null)=>{onChange(value,attachment);morphdom(document.getElementById(id),ImageInput({id:id,name:name,onChange:onChange,value:value}))};return Div({id:id,className:"image-picker"},[value?Div({id:`${id}-preview`,className:"image-input-preview",style:{backgroundImage:`url(${value})`},onClick:e=>{e.preventDefault();ImagePicker({multiple:false,onChange:attachment=>handleChange(attachment.url,attachment)})}}):null,InputGroup([Input({type:"text",id:`${id}-src`,value:value,className:"control full-width",name:name,onChange:e=>{handleChange(e.target.value,null)}}),Button({id:`${id}-select`,className:"gh-button secondary icon",onClick:e=>{e.preventDefault();ImagePicker({multiple:false,onChange:attachment=>handleChange(attachment.url,attachment)})}},icons.image)])])};const FeedbackModal=({subject:subject="",message:message="",onSubmit:onSubmit=r=>{}})=>{const State=Groundhogg.createState({subject:subject,message:message,submitting:false});ModalWithHeader({width:"400px",header:"Send Feedback"},({close,morph})=>Form({className:"display-flex column gap-5",onSubmit:e=>{e.preventDefault();State.set({submitting:true});morph();Groundhogg.api.ajax({action:"gh_plugin_feedback",subject:State.subject,message:State.message}).then(r=>{onSubmit(r);dialog({message:"Thanks for your feedback!"});close()});return false}},[Label({for:"feedback-subject"},["What feature are you submitting feedback for?"]),Input({id:"feedback-subject",value:State.subject,required:true,onInput:e=>State.set({subject:e.target.value})}),Div(),Label({for:"feedback-message"},["What is your feedback? Be as descriptive as possible."]),Textarea({id:"feedback-message",value:State.message,required:true,rows:4,onInput:e=>State.set({message:e.target.value})}),Button({className:"gh-button primary",type:"submit",disabled:State.submitting},"Send feedback"),Pg({},"Your email address will be collected to validate your feedback, but will not be used beyond that.")]))};$(document).on("click","a.feedback-modal",e=>{e.preventDefault();const{subject:subject="",message:message=""}=e.currentTarget.dataset;FeedbackModal({subject:subject,message:message})});const ContactPhone=(icon,number,extension="")=>number?Span({className:"contact-phone"},[icon,An({href:`tel:${number}`},number),extension?Span({className:"ext"},` x${extension}`):null]):null;const ContactListItem=(item,{extra:extra=item=>null,...props}={})=>{let allTags=jsonCopy(item.tags);let showTags=allTags.splice(0,10);const{ID}=item;const{full_name,gravatar,date_created,email}=item.data;const{primary_phone:primary_phone="",primary_phone_extension:primary_phone_extension="",mobile_phone:mobile_phone="",company_phone:company_phone="",company_phone_extension:company_phone_extension=""}=item.meta;return Div({className:`contact-list-item`,id:`contact-list-item-${ID}`,dataId:ID,...props},[Div({className:"display-flex gap-10"},[Img({className:"avatar",src:gravatar,alt:"avatar"}),Div({className:"display-flex column"},[Div({},[makeEl("h4",{style:{margin:0}},full_name),Span({className:"subscribed"},`&nbsp;— ${sprintf(__("Subscribed %s"),`<abbr title="${formatDateTime(date_created)}">${sprintf(__("%s ago "),item.i18n.created)}</abbr>`)}`)]),Div({},[An({href:`mailto:${email}`},email),Span({},[" — ",Span({className:`gh-text ${item.is_marketable?"green":"red"}`},Groundhogg.filters.optin_status[item.data.optin_status])])])])]),Div({className:"show-on-hover"},[primary_phone||company_phone||mobile_phone?Div({className:"contact-phones"},[ContactPhone(icons.mobile,mobile_phone),ContactPhone(icons.phone,primary_phone,primary_phone_extension),ContactPhone(icons.phone,company_phone,company_phone_extension)]):null,Div({className:"gh-tags"},[...showTags.map(tag=>Span({className:"gh-tag"},tag.data.tag_name)),allTags.length?Span({},sprintf("and %d more...",allTags.length)):null]),maybeCall(extra,item)])])};const ContactList=(contacts=[],{noContacts:noContacts=()=>null,itemProps:itemProps={}}={})=>{if(!contacts.length){return maybeCall(noContacts)}return Div({className:"contact-list"},contacts.map(contact=>ContactListItem(contact,maybeCall(itemProps,contact))))};const QuickSearch=({itemProps:itemProps={},queryOverrides:queryOverrides={}}={})=>{const State=Groundhogg.createState({search:"",searched:false,results:[],loaded:false});const fetchResults=async()=>{let results=await ContactsStore.fetchItems({search:State.search,orderby:"date_created",order:"DESC",limit:5,...queryOverrides});State.set({results:results,searched:true,loaded:true})};return Div({id:"quick-search-wrap"},morph=>{if(!State.loaded){fetchResults().then(morph)}const updateResults=debounce(async()=>{await fetchResults();morph()},300);return Fragment([Form({action:adminPageURL("gh_contacts")},[Input({type:"hidden",name:"page",value:"gh_contacts"}),Input({id:"quick-search-input",placeholder:__("Search by name or email...","groundhogg"),type:"search",name:"s",value:State.search,onInput:e=>{State.set({search:e.target.value});updateResults()}})]),State.loaded?null:Skeleton({},["full","full","full"]),State.results.length?ContactList(State.results,{itemProps:item=>({className:"contact-list-item clickable",onClick:e=>{window.open(item.admin,"_self")},...maybeCall(itemProps,item)})}):null,State.results.length===0&&State.searched?Pg({style:{textAlign:"center"}},__("No contacts found for the current search","groundhogg")):null])})};const Panel=({id,name,collapsed:collapsed=false,hidden:hidden=false,onCollapse:onCollapse=id=>{}},content)=>{if(hidden){return null}return Div({id:`${id}-panel`,className:`gh-panel ${collapsed?"closed":""}`},[Div({className:`gh-panel-header`},[H2({},name),Button({className:"toggle-indicator",onClick:e=>{onCollapse(id)}})]),collapsed?null:maybeCall(content)])};const Panels=overrides=>({...Groundhogg.createRegistry({}),storagePrefix:"gh-panels",collapse(id){if(!this.isCollapsed(id)){this.toggleCollapse(id)}},expand(id){if(this.isCollapsed(id)){this.toggleCollapse(id)}},hide(id){if(!this.isHidden(id)){this.toggleHidden(id)}},show(id){if(this.isHidden(id)){this.toggleHidden(id)}},togglePanel(id,suffix){let panels=this.getPanelIds(suffix);if(panels.includes(id)){panels.splice(panels.indexOf(id),1)}else{panels.push(id)}localStorage.setItem(`${this.storagePrefix}-${suffix}`,JSON.stringify(panels))},toggleHidden(id){this.togglePanel(id,"hidden")},toggleCollapse(id){this.togglePanel(id,"collapsed")},getPanelIds(suffix){return JSON.parse(localStorage.getItem(`${this.storagePrefix}-${suffix}`))||[]},getHiddenPanelIds(){return this.getPanelIds("hidden")},getCollapsedPanelIds(){return this.getPanelIds("collapsed")},isHidden(id){return this.getHiddenPanelIds().includes(id)},isCollapsed(id){return this.getCollapsedPanelIds().includes(id)},PanelControls(){return Div({},[...this.map((item,id)=>Div({className:"display-flex gap-10",style:{marginBottom:"10px"}},[Toggle({checked:!this.isHidden(id),id:`toggle-${id}`,onChange:e=>{this.toggleHidden(id)}}),Label({for:`toggle-${id}`},item.name)]))])},Panel(id){let{content,...panel}=this.get(id);return Panel({id:id,...panel,collapsed:this.isCollapsed(id),hidden:this.isHidden(id),onCollapse:id=>{this.toggleCollapse(id);morphdom(document.getElementById(`${id}-panel`),this.Panel(id))}},content)},Panels(){return Div({className:"display-flex column gap-20",id:this.storagePrefix},this.keys().map(id=>this.Panel(id)))},...overrides});const Relationships=({title:title="",id,store,child_type:child_type="",parent_type:parent_type="",renderItem:renderItem=item=>{},onAddItem:onAddItem=(r,j)=>{}})=>{const rel_type_key=child_type?"child_type":"parent_type";const rel_type=child_type||parent_type;const rel_id_key=child_type?"child_id":"parent_id";const State=Groundhogg.createState({loaded:false,items:[]});const fetchRelationships=()=>store.fetchRelationships(id,{[rel_type_key]:rel_type}).then(items=>State.set({items:items,loaded:true}));const deleteRelationship=itemId=>store.deleteRelationships(id,{[rel_type_key]:rel_type,[rel_id_key]:itemId}).then(()=>State.set({items:State.items.filter(item=>item.ID!==itemId)}));const createRelationship=item=>store.createRelationships(id,{[rel_type_key]:rel_type,[rel_id_key]:item.ID}).then(()=>State.set({items:[...State.items,item]}));return Div({id:`${rel_type_key}-${rel_type}-rel-of-${id}`,className:`display-flex column relationship-editor ${rel_type_key}-${rel_type}`},morph=>{const handleDeleteRelationship=itemId=>deleteRelationship(itemId).then(morph);if(!State.loaded){fetchRelationships().then(morph);return Skeleton({},["full","full","full"])}const AddRelButton=()=>Button({id:`add-${rel_type_key}-${rel_type}-rel-for-${id}`,className:"gh-button secondary text icon",onClick:e=>{let promise=new Promise((resolve,reject)=>onAddItem(resolve,reject,State));promise.then(item=>createRelationship(item).then(morph))}},[Dashicon("plus-alt2"),ToolTip(__("Add relationship","groundhogg"),"left")]);return Fragment([title?Div({className:"space-between"},[H4({},title),AddRelButton()]):null,...State.items.map(item=>renderItem({...item,onDelete:handleDeleteRelationship})),title?null:Div({className:"display-flex flex-end"},AddRelButton())])})};const OwnerPicker=({id:id="select-owners",selected:selected=[],onChange:onChange=ids=>{},allow0:allow0=true,itemDisplay:itemDisplay=user=>user.data.display_name,multiple:multiple=true,...overrides})=>ItemPicker({id:`select-users`,noneSelected:__("Select a user...","groundhogg"),selected:selected.map(user_id=>{if(user_id==0&&allow0){return{id:0,text:__("The contact owner","groundhogg")}}return{id:user_id,text:itemDisplay(getOwner(user_id))}}),multiple:multiple,style:{flexGrow:1},isValidSelection:id=>id===0||getOwner(id),fetchOptions:search=>{search=new RegExp(search,"i");let options=Groundhogg.filters.owners.map(u=>({id:u.ID,text:itemDisplay(u)}));if(allow0){options.push({id:0,text:__("The contact owner","groundhogg")})}options=options.filter(({text})=>text.match(search));return Promise.resolve(options)},onChange:items=>{if(multiple){onChange(items.map(({id})=>id));return}onChange(items)},...overrides});function getClosestRelativeAncestor(element){let parent=element.parentElement;while(parent){if(window.getComputedStyle(parent).position==="relative"){return parent}parent=parent.parentElement}return null}const Tour=(steps,{onFinish:onFinish=()=>{},beforeDismiss:beforeDismiss=({dismiss})=>dismiss(),onDismiss:onDismiss=()=>{},fixed:fixed=false})=>{const State=Groundhogg.createState({current:0,step:null,target:null,relative:null});const currentStep=()=>steps[State.current];const removeSteps=()=>{document.querySelectorAll(".tour-prompt-container").forEach(el=>el.remove());document.querySelectorAll(".tour-prompt").forEach(el=>el.remove());document.querySelectorAll(".tour-highlighted").forEach(el=>el.classList.remove("tour-highlighted"))};const remove=()=>{removeSteps();document.removeEventListener("resize",rePositionStep);document.removeEventListener("scroll",rePositionStep)};const dismiss=async()=>{remove();onDismiss()};const next=()=>{const{onNext:onNext=()=>{}}=currentStep();onNext();if(State.current+1>=steps.length){remove();onFinish(true);return}State.current++;showStep()};const prev=()=>{const{onPrev:onPrev=()=>{}}=currentStep();onPrev();if(State.current<=0){return}State.current--;showStep()};const showStep=()=>{removeSteps();positionStep()};function rePositionStep(){let{position}=currentStep();let{target,relative,step,windowEl}=State;const targetPos=target.getBoundingClientRect();const relativePos=relative.getBoundingClientRect();const stepPos=step.getBoundingClientRect();const gap=20;if(fixed){windowEl.style.height=`${targetPos.height+gap*2}px`;windowEl.style.width=`${targetPos.width+gap*2}px`;windowEl.style.borderWidth=`${Math.round(targetPos.y)-gap}px ${Math.round(window.innerWidth-targetPos.x)-gap}px ${Math.round(window.innerHeight-targetPos.y)-gap}px ${Math.round(targetPos.x)-gap}px`;switch(position){case"right":step.style.left=`${targetPos.x+targetPos.width+gap}px`;step.style.top=`${targetPos.y}px`;break;case"left":step.style.left=`${targetPos.x-stepPos.width-gap}px`;step.style.top=`${targetPos.y}px`;break;case"above":step.style.left=`${targetPos.x}px`;step.style.top=`${targetPos.y-stepPos.height-gap}px`;break;case"below":step.style.left=`${targetPos.x}px`;step.style.top=`${targetPos.y+targetPos.height+gap}px`;break;case"below-left":step.style.left=`${targetPos.x+targetPos.width-stepPos.width}px`;step.style.top=`${targetPos.y+targetPos.height+gap}px`;break}return}switch(position){case"right":step.style.left=`${targetPos.right-relativePos.left+gap}px`;step.style.top=`${targetPos.top-relativePos.top}px`;break;case"left":step.style.left=`${targetPos.left-relativePos.left-stepPos.width-gap}px`;step.style.top=`${targetPos.top-relativePos.top}px`;break;case"above":step.style.left=`${targetPos.left-relativePos.left}px`;step.style.top=`${targetPos.top-relativePos.top-stepPos.height-gap}px`;break;case"below":step.style.left=`${targetPos.left-relativePos.left}px`;step.style.top=`${targetPos.bottom-relativePos.top+gap}px`;break;case"below-left":step.style.left=`${targetPos.right-relativePos.left-stepPos.width}px`;step.style.top=`${targetPos.bottom-relativePos.top+gap}px`;break}}function positionStep(){let tourEl=TourStep();let windowEl=tourEl.querySelector(".tour-window");let stepEl=tourEl.querySelector(".tour-prompt");let{target,relative,onInit:onInit=()=>{},onBefore:onBefore=()=>{}}=currentStep();target=document.querySelector(target);if(!target){next();return}if(fixed){relative=document.body}else if(relative){relative=target.closest(relative)}else{relative=getClosestRelativeAncestor(target)}stepEl.style.position=fixed?"fixed":"absolute";if(fixed){relative.append(tourEl)}else{target.classList.add("tour-highlighted");relative.append(stepEl)}target.scrollIntoView({behavior:"instant",block:"center",inline:"center"});onBefore({next:next,prev:prev,target:target,relative:relative,step:stepEl,windowEl:windowEl,currentStep:currentStep});State.set({step:stepEl,windowEl:windowEl,target:target,relative:relative});rePositionStep();onInit({next:next,prev:prev,target:target,relative:relative,step:stepEl,windowEl:windowEl,currentStep:currentStep});stepEl.querySelector("#tour-next").focus()}const TourStep=()=>MakeEl.Div({className:"tour-prompt-container"},[fixed?MakeEl.Div({className:"tour-window"},[MakeEl.Div({className:"tour-window-shadow",onClick:next})]):null,MakeEl.Div({className:`tour-prompt ${currentStep().position}`,style:{padding:"10px",width:"200px"}},[MakeEl.Button({className:"dismiss",onClick:e=>{beforeDismiss({dismiss:dismiss,State:State})}},MakeEl.Dashicon("no-alt")),MakeEl.Div({},currentStep().prompt),MakeEl.Div({className:"display-flex flex-end gap-5 space-above-10"},[State.current>0?MakeEl.Button({id:"tour-prev",className:"gh-button small secondary text prev-step",onClick:()=>prev()},"Prev"):null,currentStep().showNext===false?null:MakeEl.Button({id:"tour-next",className:`gh-button small ${State.current<steps.length-1?"secondary":"primary"} next-step`,onClick:()=>next()},State.current<steps.length-1?"Next":"Finish")])])]);document.addEventListener("resize",rePositionStep);document.addEventListener("scroll",rePositionStep);positionStep()};Groundhogg.components={QuickSearch:QuickSearch,addContactModal:addContactModal,internalForm:internalForm,betterTagPicker:betterTagPicker,quickAddForm:quickAddForm,selectContactModal:selectContactModal,quickEditContactModal:quickEditContactModal,makeInput:makeInput,emailModal:emailModal,EmailTemplateModal:EmailTemplateModal,fileUploader:fileUploader,EmailPreview:EmailPreview,EmailPreviewModal:EmailPreviewModal,ImageInput:ImageInput,ImagePicker:ImagePicker,FeedbackModal:FeedbackModal,ContactList:ContactList,ContactListItem:ContactListItem,Panel:Panel,Panels:Panels,Relationships:Relationships,OwnerPicker:OwnerPicker,Tour:Tour}})(jQuery);
     218      `,onOpen:({close})=>{let file=null;let filesToUpload=[];let filesUploaded=[];let uploading=false;const pushFiles=()=>{renderUploadingFiles();file=filesToUpload.pop();if(!file){uploading=false;return}uploading=true;let fd=new FormData;fd.append(fileName,file,file.name);fd.append("gh_admin_ajax_nonce",Groundhogg.nonces._adminajax);fd.append("action",action);beforeUpload(fd);setTimeout(()=>{fetch(ajaxurl,{method:"POST",credentials:"same-origin",body:fd}).then(r=>{if(!r.ok){dialog({message:__("Something when wrong..."),type:"error"});return}return r.json()}).then(r=>{if(!r.success){dialog({message:r.data[0].message,type:"error"});pushFiles();return}onUpload(r,file);filesUploaded.unshift(file);renderUploadedFiles();pushFiles()})},2e3)};const renderUploadingFiles=()=>{$("#uploading-files").html(filesToUpload.map(f=>`<div class="file"><span class="hourglass">⌛</span> ${f.name}</div>`))};const renderUploadedFiles=()=>{$("#uploaded-files").html(filesUploaded.map(f=>`<div class="file">✅ ${f.name}</div>`))};const addFiles=files=>{filesToUpload.push(...files);if(!uploading){pushFiles()}};const $input=$("#upload-file-input");$input.on("change",e=>{addFiles(e.target.files)});$("#select-files").on("click",e=>{e.preventDefault();$input.click()});const $droppable=$(".droppable-handler");$droppable.on("dragover",e=>{e.preventDefault();$droppable.addClass("dragover")}).on("dragleave",e=>{$droppable.removeClass("dragover")}).on("drop",e=>{e.preventDefault();$droppable.removeClass("dragover");let{dataTransfer}=e.originalEvent;addFiles(dataTransfer.files)})}})};const EmailPreviewModal=async(emailId,{height=window.innerHeight*.85,width=900})=>{const{close}=loadingModal();let email;try{email=await EmailsStore.maybeFetchItem(emailId)}catch(err){close();throw err}const{from_avatar,from_email,from_name,subject,built:content}=email.context;close();return ModalFrame({frameAttributes:{className:"gh-modal-frame gh-email-preview-modal"}},({close})=>Div({style:{width:`${width}px`,height:`${height}px`}},EmailPreview({close:close,from_avatar:from_avatar,from_email:from_email,from_name:from_name,subject:subject,content:content})))};const EmailPreview=({close=false,from_avatar,from_email,from_name,subject,content})=>{return Div({className:"email-preview"},[Div({className:"from-preview display-flex gap-20 has-box-shadow"},[makeEl("img",{src:from_avatar,className:"from-avatar",height:40,width:40,style:{borderRadius:"50%"}}),Div({className:"subject-and-from"},[`<h2>${subject}</h2>`,`<span class="from-name">${from_name}</span> <span class="from-email">&lt;${from_email}&gt;</span>`]),close!==false?Button({className:"gh-button secondary icon text",style:{marginLeft:"auto"},onClick:close},Dashicon("no-alt")):null]),Iframe({id:"desktop-preview-iframe"},content)])};$(()=>{$(document).on("click","a.gh-email-preview",e=>{e.preventDefault();let emailId=e.currentTarget.dataset.id??e.currentTarget.closest("tr").id;EmailPreviewModal(parseInt(emailId),{})})});const ImagePicker=({multiple=false,title=__("Select a image to upload"),selectText=__("Use this image"),onChange=attachment=>{}})=>{let file_frame=wp.media({title:title,button:{text:selectText},multiple:multiple});file_frame.on("select",function(){let attachment=file_frame.state().get("selection").first().toJSON();onChange(attachment)});file_frame.open()};const ImageInput=({id,name="src",onChange,value=""})=>{const handleChange=(value,attachment=null)=>{onChange(value,attachment);morphdom(document.getElementById(id),ImageInput({id:id,name:name,onChange:onChange,value:value}))};return Div({id:id,className:"image-picker"},[value?Div({id:`${id}-preview`,className:"image-input-preview",style:{backgroundImage:`url(${value})`},onClick:e=>{e.preventDefault();ImagePicker({multiple:false,onChange:attachment=>handleChange(attachment.url,attachment)})}}):null,InputGroup([Input({type:"text",id:`${id}-src`,value:value,className:"control full-width",name:name,onChange:e=>{handleChange(e.target.value,null)}}),Button({id:`${id}-select`,className:"gh-button secondary icon",onClick:e=>{e.preventDefault();ImagePicker({multiple:false,onChange:attachment=>handleChange(attachment.url,attachment)})}},icons.image)])])};const FeedbackModal=({subject="",message="",onSubmit=r=>{}})=>{const State=Groundhogg.createState({subject:subject,message:message,submitting:false});ModalWithHeader({width:"400px",header:"Send Feedback"},({close,morph})=>Form({className:"display-flex column gap-5",onSubmit:e=>{e.preventDefault();State.set({submitting:true});morph();Groundhogg.api.ajax({action:"gh_plugin_feedback",subject:State.subject,message:State.message}).then(r=>{onSubmit(r);dialog({message:"Thanks for your feedback!"});close()});return false}},[Label({for:"feedback-subject"},["What feature are you submitting feedback for?"]),Input({id:"feedback-subject",value:State.subject,required:true,onInput:e=>State.set({subject:e.target.value})}),Div(),Label({for:"feedback-message"},["What is your feedback? Be as descriptive as possible."]),Textarea({id:"feedback-message",value:State.message,required:true,rows:4,onInput:e=>State.set({message:e.target.value})}),Button({className:"gh-button primary",type:"submit",disabled:State.submitting},"Send feedback"),Pg({},"Your email address will be collected to validate your feedback, but will not be used beyond that.")]))};$(document).on("click","a.feedback-modal",e=>{e.preventDefault();const{subject="",message=""}=e.currentTarget.dataset;FeedbackModal({subject:subject,message:message})});const ContactPhone=(icon,number,extension="")=>number?Span({className:"contact-phone"},[icon,An({href:`tel:${number}`},number),extension?Span({className:"ext"},` x${extension}`):null]):null;const ContactListItem=(item,{extra=item=>null,...props}={})=>{let allTags=jsonCopy(item.tags);let showTags=allTags.splice(0,10);const{ID}=item;const{full_name,gravatar,date_created,email}=item.data;const{primary_phone="",primary_phone_extension="",mobile_phone="",company_phone="",company_phone_extension=""}=item.meta;return Div({className:`contact-list-item`,id:`contact-list-item-${ID}`,dataId:ID,...props},[Div({className:"display-flex gap-10"},[Img({className:"avatar",src:gravatar,alt:"avatar"}),Div({className:"display-flex column"},[Div({},[makeEl("h4",{style:{margin:0}},full_name),Span({className:"subscribed"},`&nbsp;— ${sprintf(__("Subscribed %s"),`<abbr title="${formatDateTime(date_created)}">${sprintf(__("%s ago "),item.i18n.created)}</abbr>`)}`)]),Div({},[An({href:`mailto:${email}`},email),Span({},[" — ",Span({className:`gh-text ${item.is_marketable?"green":"red"}`},Groundhogg.filters.optin_status[item.data.optin_status])])])])]),Div({className:"show-on-hover"},[primary_phone||company_phone||mobile_phone?Div({className:"contact-phones"},[ContactPhone(icons.mobile,mobile_phone),ContactPhone(icons.phone,primary_phone,primary_phone_extension),ContactPhone(icons.phone,company_phone,company_phone_extension)]):null,Div({className:"gh-tags"},[...showTags.map(tag=>Span({className:"gh-tag"},tag.data.tag_name)),allTags.length?Span({},sprintf("and %d more...",allTags.length)):null]),maybeCall(extra,item)])])};const ContactList=(contacts=[],{noContacts=()=>null,itemProps={}}={})=>{if(!contacts.length){return maybeCall(noContacts)}return Div({className:"contact-list"},contacts.map(contact=>ContactListItem(contact,maybeCall(itemProps,contact))))};const QuickSearch=({itemProps={},queryOverrides={}}={})=>{const State=Groundhogg.createState({search:"",searched:false,results:[],loaded:false});const fetchResults=async()=>{let results=await ContactsStore.fetchItems({search:State.search,orderby:"date_created",order:"DESC",limit:5,...queryOverrides});State.set({results:results,searched:true,loaded:true})};return Div({id:"quick-search-wrap"},morph=>{if(!State.loaded){fetchResults().then(morph)}const updateResults=debounce(async()=>{await fetchResults();morph()},300);return Fragment([Form({action:adminPageURL("gh_contacts")},[Input({type:"hidden",name:"page",value:"gh_contacts"}),Input({id:"quick-search-input",placeholder:__("Search by name or email...","groundhogg"),type:"search",name:"s",value:State.search,onInput:e=>{State.set({search:e.target.value});updateResults()}})]),State.loaded?null:Skeleton({},["full","full","full"]),State.results.length?ContactList(State.results,{itemProps:item=>({className:"contact-list-item clickable",onClick:e=>{window.open(item.admin,"_self")},...maybeCall(itemProps,item)})}):null,State.results.length===0&&State.searched?Pg({style:{textAlign:"center"}},__("No contacts found for the current search","groundhogg")):null])})};const Panel=({id,name,collapsed=false,hidden=false,onCollapse=id=>{}},content)=>{if(hidden){return null}return Div({id:`${id}-panel`,className:`gh-panel ${collapsed?"closed":""}`},[Div({className:`gh-panel-header`},[H2({},name),Button({className:"toggle-indicator",onClick:e=>{onCollapse(id)}})]),collapsed?null:maybeCall(content)])};const Panels=overrides=>({...Groundhogg.createRegistry({}),storagePrefix:"gh-panels",collapse(id){if(!this.isCollapsed(id)){this.toggleCollapse(id)}},expand(id){if(this.isCollapsed(id)){this.toggleCollapse(id)}},hide(id){if(!this.isHidden(id)){this.toggleHidden(id)}},show(id){if(this.isHidden(id)){this.toggleHidden(id)}},togglePanel(id,suffix){let panels=this.getPanelIds(suffix);if(panels.includes(id)){panels.splice(panels.indexOf(id),1)}else{panels.push(id)}localStorage.setItem(`${this.storagePrefix}-${suffix}`,JSON.stringify(panels))},toggleHidden(id){this.togglePanel(id,"hidden")},toggleCollapse(id){this.togglePanel(id,"collapsed")},getPanelIds(suffix){return JSON.parse(localStorage.getItem(`${this.storagePrefix}-${suffix}`))||[]},getHiddenPanelIds(){return this.getPanelIds("hidden")},getCollapsedPanelIds(){return this.getPanelIds("collapsed")},isHidden(id){return this.getHiddenPanelIds().includes(id)},isCollapsed(id){return this.getCollapsedPanelIds().includes(id)},PanelControls(){return Div({},[...this.map((item,id)=>Div({className:"display-flex gap-10",style:{marginBottom:"10px"}},[Toggle({checked:!this.isHidden(id),id:`toggle-${id}`,onChange:e=>{this.toggleHidden(id)}}),Label({for:`toggle-${id}`},item.name)]))])},Panel(id){let{content,...panel}=this.get(id);return Panel({id:id,...panel,collapsed:this.isCollapsed(id),hidden:this.isHidden(id),onCollapse:id=>{this.toggleCollapse(id);morphdom(document.getElementById(`${id}-panel`),this.Panel(id))}},content)},Panels(){return Div({className:"display-flex column gap-20",id:this.storagePrefix},this.keys().map(id=>this.Panel(id)))},...overrides});const Relationships=({title="",id,store,child_type="",parent_type="",renderItem=item=>{},onAddItem=(r,j)=>{}})=>{const rel_type_key=child_type?"child_type":"parent_type";const rel_type=child_type||parent_type;const rel_id_key=child_type?"child_id":"parent_id";const State=Groundhogg.createState({loaded:false,items:[]});const fetchRelationships=()=>store.fetchRelationships(id,{[rel_type_key]:rel_type}).then(items=>State.set({items:items,loaded:true}));const deleteRelationship=itemId=>store.deleteRelationships(id,{[rel_type_key]:rel_type,[rel_id_key]:itemId}).then(()=>State.set({items:State.items.filter(item=>item.ID!==itemId)}));const createRelationship=item=>store.createRelationships(id,{[rel_type_key]:rel_type,[rel_id_key]:item.ID}).then(()=>State.set({items:[...State.items,item]}));return Div({id:`${rel_type_key}-${rel_type}-rel-of-${id}`,className:`display-flex column relationship-editor ${rel_type_key}-${rel_type}`},morph=>{const handleDeleteRelationship=itemId=>deleteRelationship(itemId).then(morph);if(!State.loaded){fetchRelationships().then(morph);return Skeleton({},["full","full","full"])}const AddRelButton=()=>Button({id:`add-${rel_type_key}-${rel_type}-rel-for-${id}`,className:"gh-button secondary text icon",onClick:e=>{let promise=new Promise((resolve,reject)=>onAddItem(resolve,reject,State));promise.then(item=>createRelationship(item).then(morph))}},[Dashicon("plus-alt2"),ToolTip(__("Add relationship","groundhogg"),"left")]);return Fragment([title?Div({className:"space-between"},[H4({},title),AddRelButton()]):null,...State.items.map(item=>renderItem({...item,onDelete:handleDeleteRelationship})),title?null:Div({className:"display-flex flex-end"},AddRelButton())])})};const OwnerPicker=({id="select-owners",selected=[],onChange=ids=>{},allow0=true,itemDisplay=user=>user.data.display_name,multiple=true,...overrides})=>ItemPicker({id:`select-users`,noneSelected:__("Select a user...","groundhogg"),selected:selected.map(user_id=>{if(user_id==0&&allow0){return{id:0,text:__("The contact owner","groundhogg")}}return{id:user_id,text:itemDisplay(getOwner(user_id))}}),multiple:multiple,style:{flexGrow:1},isValidSelection:id=>id===0||getOwner(id),fetchOptions:search=>{search=new RegExp(search,"i");let options=Groundhogg.filters.owners.map(u=>({id:u.ID,text:itemDisplay(u)}));if(allow0){options.push({id:0,text:__("The contact owner","groundhogg")})}options=options.filter(({text})=>text.match(search));return Promise.resolve(options)},onChange:items=>{if(multiple){onChange(items.map(({id})=>id));return}onChange(items)},...overrides});function getClosestRelativeAncestor(element){let parent=element.parentElement;while(parent){if(window.getComputedStyle(parent).position==="relative"){return parent}parent=parent.parentElement}return null}const Tour=(steps,{onFinish=()=>{},beforeDismiss=({dismiss})=>dismiss(),onDismiss=()=>{},fixed=false})=>{const State=Groundhogg.createState({current:0,step:null,target:null,relative:null});const currentStep=()=>steps[State.current];const removeSteps=()=>{document.querySelectorAll(".tour-prompt-container").forEach(el=>el.remove());document.querySelectorAll(".tour-prompt").forEach(el=>el.remove());document.querySelectorAll(".tour-highlighted").forEach(el=>el.classList.remove("tour-highlighted"))};const remove=()=>{removeSteps();document.removeEventListener("resize",rePositionStep);document.removeEventListener("scroll",rePositionStep)};const dismiss=async()=>{remove();onDismiss()};const next=()=>{const{onNext=()=>{}}=currentStep();onNext();if(State.current+1>=steps.length){remove();onFinish(true);return}State.current++;showStep()};const prev=()=>{const{onPrev=()=>{}}=currentStep();onPrev();if(State.current<=0){return}State.current--;showStep()};const showStep=()=>{removeSteps();positionStep()};function rePositionStep(){let{position}=currentStep();let{target,relative,step,windowEl}=State;const targetPos=target.getBoundingClientRect();const relativePos=relative.getBoundingClientRect();const stepPos=step.getBoundingClientRect();const gap=20;if(fixed){windowEl.style.height=`${targetPos.height+gap*2}px`;windowEl.style.width=`${targetPos.width+gap*2}px`;windowEl.style.borderWidth=`${Math.round(targetPos.y)-gap}px ${Math.round(window.innerWidth-targetPos.x)-gap}px ${Math.round(window.innerHeight-targetPos.y)-gap}px ${Math.round(targetPos.x)-gap}px`;switch(position){case"right":step.style.left=`${targetPos.x+targetPos.width+gap}px`;step.style.top=`${targetPos.y}px`;break;case"left":step.style.left=`${targetPos.x-stepPos.width-gap}px`;step.style.top=`${targetPos.y}px`;break;case"above":step.style.left=`${targetPos.x}px`;step.style.top=`${targetPos.y-stepPos.height-gap}px`;break;case"below":step.style.left=`${targetPos.x}px`;step.style.top=`${targetPos.y+targetPos.height+gap}px`;break;case"below-left":step.style.left=`${targetPos.x+targetPos.width-stepPos.width}px`;step.style.top=`${targetPos.y+targetPos.height+gap}px`;break}return}switch(position){case"right":step.style.left=`${targetPos.right-relativePos.left+gap}px`;step.style.top=`${targetPos.top-relativePos.top}px`;break;case"left":step.style.left=`${targetPos.left-relativePos.left-stepPos.width-gap}px`;step.style.top=`${targetPos.top-relativePos.top}px`;break;case"above":step.style.left=`${targetPos.left-relativePos.left}px`;step.style.top=`${targetPos.top-relativePos.top-stepPos.height-gap}px`;break;case"below":step.style.left=`${targetPos.left-relativePos.left}px`;step.style.top=`${targetPos.bottom-relativePos.top+gap}px`;break;case"below-left":step.style.left=`${targetPos.right-relativePos.left-stepPos.width}px`;step.style.top=`${targetPos.bottom-relativePos.top+gap}px`;break}}function positionStep(){let tourEl=TourStep();let windowEl=tourEl.querySelector(".tour-window");let stepEl=tourEl.querySelector(".tour-prompt");let{target,relative,onInit=()=>{},onBefore=()=>{}}=currentStep();target=document.querySelector(target);if(!target){next();return}if(fixed){relative=document.body}else if(relative){relative=target.closest(relative)}else{relative=getClosestRelativeAncestor(target)}stepEl.style.position=fixed?"fixed":"absolute";if(fixed){relative.append(tourEl)}else{target.classList.add("tour-highlighted");relative.append(stepEl)}target.scrollIntoView({behavior:"instant",block:"center",inline:"center"});onBefore({next:next,prev:prev,target:target,relative:relative,step:stepEl,windowEl:windowEl,currentStep:currentStep});State.set({step:stepEl,windowEl:windowEl,target:target,relative:relative});rePositionStep();onInit({next:next,prev:prev,target:target,relative:relative,step:stepEl,windowEl:windowEl,currentStep:currentStep});stepEl.querySelector("#tour-next").focus()}const TourStep=()=>MakeEl.Div({className:"tour-prompt-container"},[fixed?MakeEl.Div({className:"tour-window"},[MakeEl.Div({className:"tour-window-shadow",onClick:next})]):null,MakeEl.Div({className:`tour-prompt ${currentStep().position}`,style:{padding:"10px",width:"200px"}},[MakeEl.Button({className:"dismiss",onClick:e=>{beforeDismiss({dismiss:dismiss,State:State})}},MakeEl.Dashicon("no-alt")),MakeEl.Div({},currentStep().prompt),MakeEl.Div({className:"display-flex flex-end gap-5 space-above-10"},[State.current>0?MakeEl.Button({id:"tour-prev",className:"gh-button small secondary text prev-step",onClick:()=>prev()},"Prev"):null,currentStep().showNext===false?null:MakeEl.Button({id:"tour-next",className:`gh-button small ${State.current<steps.length-1?"secondary":"primary"} next-step`,onClick:()=>next()},State.current<steps.length-1?"Next":"Finish")])])]);document.addEventListener("resize",rePositionStep);document.addEventListener("scroll",rePositionStep);positionStep()};Groundhogg.components={QuickSearch:QuickSearch,addContactModal:addContactModal,internalForm:internalForm,betterTagPicker:betterTagPicker,quickAddForm:quickAddForm,selectContactModal:selectContactModal,quickEditContactModal:quickEditContactModal,makeInput:makeInput,emailModal:emailModal,EmailTemplateModal:EmailTemplateModal,fileUploader:fileUploader,EmailPreview:EmailPreview,EmailPreviewModal:EmailPreviewModal,ImageInput:ImageInput,ImagePicker:ImagePicker,FeedbackModal:FeedbackModal,ContactList:ContactList,ContactListItem:ContactListItem,Panel:Panel,Panels:Panels,Relationships:Relationships,OwnerPicker:OwnerPicker,Tour:Tour}})(jQuery);
  • groundhogg/tags/4.2.9/assets/js/admin/filters/contacts.js

    r3335438 r3400645  
    24362436  ContactFilterRegistry.registerFilter(CurrentDateCompareFilterFactory('current_time', 'Current Time', 'time', ( time ) => formatTime(`2000-01-01T${time}`) ))
    24372437
     2438  const dayList = {
     2439    0: __('Sunday'),
     2440    1: __('Monday'),
     2441    2: __('Tuesday'),
     2442    3: __('Wednesday'),
     2443    4: __('Thursday'),
     2444    5: __('Friday'),
     2445    6: __('Saturday'),
     2446  }
     2447
     2448  ContactFilterRegistry.registerFilter(createFilter('day_of_week', 'Day of Week', 'date', {
     2449    edit   : ({
     2450      days = [],
     2451      updateFilter,
     2452    }) => {
     2453
     2454      return ItemPicker({
     2455        id          : 'days-of-week-picker',
     2456        noneSelected: 'Select a day',
     2457        fetchOptions: async (search) => assoc2array(dayList).filter(option => option.text.match(new RegExp(search, 'i'))),
     2458        selected    : days.map(day => ( {
     2459          id  : day,
     2460          text: dayList[day],
     2461        } )),
     2462        onChange    : items => {
     2463          updateFilter({
     2464            days: items.map(item => item.id),
     2465          })
     2466        },
     2467      })
     2468
     2469    },
     2470    display: ({ days = [] }) => sprintf(__('Today is a %s'), orList(days.map(day => bold(dayList[day])))),
     2471  }))
     2472
     2473  const dateList = {
     2474    1 : __('1st'),
     2475    2 : __('2nd'),
     2476    3 : __('3rd'),
     2477    4 : __('4th'),
     2478    5 : __('5th'),
     2479    6 : __('6th'),
     2480    7 : __('7th'),
     2481    8 : __('8th'),
     2482    9 : __('9th'),
     2483    10: __('10th'),
     2484    11: __('11th'),
     2485    12: __('12th'),
     2486    13: __('13th'),
     2487    14: __('14th'),
     2488    15: __('15th'),
     2489    16: __('16th'),
     2490    17: __('17th'),
     2491    18: __('18th'),
     2492    19: __('19th'),
     2493    20: __('20th'),
     2494    21: __('21st'),
     2495    22: __('22nd'),
     2496    23: __('23rd'),
     2497    24: __('24th'),
     2498    25: __('25th'),
     2499    26: __('26th'),
     2500    27: __('27th'),
     2501    28: __('28th'),
     2502    29: __('29th'),
     2503    30: __('30th'),
     2504    31: __('31st'),
     2505    0 : __('Last'),
     2506  }
     2507
     2508  ContactFilterRegistry.registerFilter(createFilter('day_of_month', 'Day of Month', 'date', {
     2509    edit   : ({
     2510      dates = [],
     2511      updateFilter,
     2512    }) => {
     2513
     2514      return ItemPicker({
     2515        id          : 'days-of-week-picker',
     2516        noneSelected: 'Select a day',
     2517        fetchOptions: async (search) => assoc2array(dateList).filter(option => option.text.match(new RegExp(search, 'i'))),
     2518        selected    : dates.map(date => ( {
     2519          id  : date,
     2520          text: dateList[date],
     2521        } )),
     2522        onChange    : items => {
     2523          updateFilter({
     2524            dates: items.map(item => item.id),
     2525          })
     2526        },
     2527      })
     2528
     2529    },
     2530    display: ({ dates = [] }) => sprintf(__('Today is the %s of the month'), orList(dates.map(date => bold(dateList[date])))),
     2531  }))
     2532
    24382533  registerFilterGroup( 'submissions', 'Submissions' )
    24392534
     
    25932688  }
    25942689
     2690  ContactFilterRegistry.registerFilter(createPastDateFilter('wp_fusion_activity', 'WP Fusion', 'activity', {
     2691    display: ({
     2692      event_name = '',
     2693      event_name_compare,
     2694      event_value = '',
     2695      event_value_compare,
     2696    }) => {
     2697
     2698      if (!event_name) {
     2699        return 'Any WP Fusion activity'
     2700      }
     2701
     2702      let text = sprintf(`WP Fusion Event: %s`,
     2703        ComparisonsTitleGenerators[event_name_compare](bold('Name'), `<code>${ event_name }</code>`),
     2704      )
     2705
     2706      if (event_value) {
     2707        text += ', ' + ComparisonsTitleGenerators[event_value_compare](bold('Value'), `<code>${ event_value }</code>`)
     2708      }
     2709
     2710      return text
     2711    },
     2712    edit   : ({
     2713      event_name = '',
     2714      event_value = '',
     2715      event_value_compare = 'equals',
     2716      event_name_compare = 'equals',
     2717      updateFilter = () => {},
     2718    }) => {
     2719
     2720      return Fragment([
     2721        MakeEl.Label({ for: 'event-name' }, 'Event Name'),
     2722        MakeEl.InputGroup([
     2723          Select({
     2724            id      : 'event-name-compare',
     2725            name    : 'event_name_compare',
     2726            selected: event_name_compare,
     2727            options : StringComparisons,
     2728            onChange: e => {
     2729              updateFilter({
     2730                event_name_compare: e.target.value,
     2731              })
     2732            },
     2733          }),
     2734          Input({
     2735            id         : 'event-name',
     2736            name       : 'event_name',
     2737            value      : event_name,
     2738            placeholder: 'Event Name',
     2739            onChange   : e => {
     2740              updateFilter({
     2741                event_name: e.target.value,
     2742              })
     2743            },
     2744          }),
     2745        ]),
     2746        MakeEl.Label({ for: 'event-value' }, 'Event Value'),
     2747        MakeEl.InputGroup([
     2748          Select({
     2749            id      : 'event-value-compare',
     2750            selected: event_value_compare,
     2751            options : AllComparisons,
     2752            onChange: e => {
     2753              updateFilter({
     2754                event_value_compare: e.target.value,
     2755              })
     2756            },
     2757          }),
     2758          Input({
     2759            id         : 'event-value',
     2760            value      : event_value,
     2761            placeholder: 'Event value',
     2762            onChange   : e => {
     2763              updateFilter({
     2764                event_value: e.target.value,
     2765              })
     2766            },
     2767          }),
     2768        ]),
     2769      ])
     2770    },
     2771  }, {
     2772    event_name_compare : 'equals',
     2773    event_name         : '',
     2774    event_value_compare: 'equals',
     2775    event_value        : '',
     2776  }))
     2777
    25952778  if (typeof Groundhogg.rawStepTypes.webhook_listener !== 'undefined') {
    25962779    ContactFilterRegistry.registerFilter(createPastDateFilter('webhook_request', 'Webhook Request', 'submissions', {
  • groundhogg/tags/4.2.9/assets/js/admin/filters/contacts.min.js

    r3335438 r3400645  
    1 (function($){const{input,select,orList,andList,bold,inputRepeater}=Groundhogg.element;const{broadcastPicker,funnelPicker,tagPicker,emailPicker,linkPicker,metaValuePicker,metaPicker,userMetaPicker}=Groundhogg.pickers;const{assoc2array}=Groundhogg.functions;const{broadcasts:BroadcastsStore,emails:EmailsStore,tags:TagsStore,funnels:FunnelsStore,searches:SearchesStore}=Groundhogg.stores;const{sprintf,__,_x,_n}=wp.i18n;const{formatDate,formatDateTime,formatTime}=Groundhogg.formatting;const{Fragment,ItemPicker,Select,Input,Div,makeEl,InputRepeater}=MakeEl;const{Filters,FilterRegistry,createFilter,createGroup,FilterDisplay,createDateFilter,createPastDateFilter,createStringFilter,createNumberFilter,createTimeFilter,unsubReasons}=Groundhogg.filters;const{ComparisonsTitleGenerators,AllComparisons,StringComparisons,NumericComparisons,pastDateRanges,futureDateRanges,allDateRanges}=Groundhogg.filters.comparisons;const ContactFilterRegistry=FilterRegistry({});const uid=function(){return Date.now().toString(36)+Math.random().toString(36).substring(2)};const createFilters=(el="",filters=[],onChange=f=>{console.log(f)})=>({el:el,onChange:onChange,filters:Array.isArray(filters)?filters:[],id:uid(),init(){this.mount()},mount(){let container=document.querySelector(el);container.innerHTML="";document.querySelector(el).appendChild(ContactFilters(this.id,this.filters,this.onChange))}});const ContactFilters=(id,filters,onChange)=>Filters({id:id,filterRegistry:ContactFilterRegistry,filters:filters,onChange:onChange});const ContactFilterDisplay=filters=>FilterDisplay({filters:filters,filterRegistry:ContactFilterRegistry});const registerFilterGroup=(group,name)=>{ContactFilterRegistry.registerGroup(createGroup(group,name))};const registerFilter=(type,group="general",name="",opts={})=>{if(typeof name==="object"){let tempOpts=name;name=tempOpts.name;opts=tempOpts}const{defaults:defaults={},preload:preload=()=>{},view:view=()=>"",edit:edit=()=>"",onMount:onMount=()=>""}=opts;ContactFilterRegistry.registerFilter(createFilter(type,name,group,{display:view,preload:preload,edit:({updateFilter,...filter})=>Fragment([edit(filter)],{onCreate:el=>{setTimeout(()=>{onMount(filter,updateFilter)},50)}})},defaults))};const standardActivityDateFilterOnMount=(filter,updateFilter)=>{$("#filter-date-range, #filter-before, #filter-after, #filter-days").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()});if($el.prop("name")==="date_range"){const $before=$("#filter-before");const $after=$("#filter-after");const $days=$("#filter-days");$before.addClass("hidden");$after.addClass("hidden");$days.addClass("hidden");switch($el.val()){case"between":$before.removeClass("hidden");$after.removeClass("hidden");break;case"day_of":case"after":$after.removeClass("hidden");break;case"before":$before.removeClass("hidden");break;case"x_days":$days.removeClass("hidden");break}}})};const standardActivityDateTitle=(prepend,{date_range,before,after,days:days=0,future:future=false})=>{let ranges=future?futureDateRanges:pastDateRanges;switch(date_range){default:return`${prepend} ${ranges[date_range]?ranges[date_range].replace("X",days).toLowerCase():""}`;case"between":return`${prepend} ${sprintf(_x("between %1$s and %2$s","where %1 and %2 are dates","groundhogg"),`<b>${formatDate(after)}</b>`,`<b>${formatDate(before)}</b>`)}`;case"before":return`${prepend} ${sprintf(_x("before %s","%s is a date","groundhogg"),`<b>${formatDate(before)}</b>`)}`;case"after":return`${prepend} ${sprintf(_x("after %s","%s is a date","groundhogg"),`<b>${formatDate(after)}</b>`)}`;case"day_of":return`${prepend} ${sprintf(_x("on %s","%s is a date","groundhogg"),`<b>${formatDate(after)}</b>`)}`}};const standardActivityDateOptions=({date_range:date_range="24_hours",after:after="",before:before="",days:days=0,future:future=false})=>{return[select({id:"filter-date-range",name:"date_range"},future?futureDateRanges:pastDateRanges,date_range),input({type:"date",value:after.split(" ")[0],id:"filter-after",className:`date ${["between","after","day_of"].includes(date_range)?"":"hidden"}`,name:"after"}),input({type:"date",value:before.split(" ")[0],id:"filter-before",className:`value ${["between","before"].includes(date_range)?"":"hidden"}`,name:"before"}),input({type:"number",value:days,id:"filter-days",min:0,className:`value ${["x_days","next_x_days"].includes(date_range)?"":"hidden"}`,name:"days"})].join("")};const standardActivityDateDefaults={date_range:"any",before:"",after:"",count:1,days:0};const filterCountDefaults={count:1,count_compare:"greater_than_or_equal_to"};const activityFilterComparisons={equals:_x("Exactly","comparison","groundhogg"),less_than:_x("Less than","comparison","groundhogg"),greater_than:_x("More than","comparison","groundhogg"),less_than_or_equal_to:_x("At most","comparison","groundhogg"),greater_than_or_equal_to:_x("At least","comparison","groundhogg")};const filterCount=({count,count_compare})=>{return`
     1(function($){const{input,select,orList,andList,bold,inputRepeater}=Groundhogg.element;const{broadcastPicker,funnelPicker,tagPicker,emailPicker,linkPicker,metaValuePicker,metaPicker,userMetaPicker}=Groundhogg.pickers;const{assoc2array}=Groundhogg.functions;const{broadcasts:BroadcastsStore,emails:EmailsStore,tags:TagsStore,funnels:FunnelsStore,searches:SearchesStore}=Groundhogg.stores;const{sprintf,__,_x,_n}=wp.i18n;const{formatDate,formatDateTime,formatTime}=Groundhogg.formatting;const{Fragment,ItemPicker,Select,Input,Div,makeEl,InputRepeater}=MakeEl;const{Filters,FilterRegistry,createFilter,createGroup,FilterDisplay,createDateFilter,createPastDateFilter,createStringFilter,createNumberFilter,createTimeFilter,unsubReasons}=Groundhogg.filters;const{ComparisonsTitleGenerators,AllComparisons,StringComparisons,NumericComparisons,pastDateRanges,futureDateRanges,allDateRanges}=Groundhogg.filters.comparisons;const ContactFilterRegistry=FilterRegistry({});const uid=function(){return Date.now().toString(36)+Math.random().toString(36).substring(2)};const createFilters=(el="",filters=[],onChange=f=>{console.log(f)})=>({el:el,onChange:onChange,filters:Array.isArray(filters)?filters:[],id:uid(),init(){this.mount()},mount(){let container=document.querySelector(el);container.innerHTML="";document.querySelector(el).appendChild(ContactFilters(this.id,this.filters,this.onChange))}});const ContactFilters=(id,filters,onChange)=>Filters({id:id,filterRegistry:ContactFilterRegistry,filters:filters,onChange:onChange});const ContactFilterDisplay=filters=>FilterDisplay({filters:filters,filterRegistry:ContactFilterRegistry});const registerFilterGroup=(group,name)=>{ContactFilterRegistry.registerGroup(createGroup(group,name))};const registerFilter=(type,group="general",name="",opts={})=>{if(typeof name==="object"){let tempOpts=name;name=tempOpts.name;opts=tempOpts}const{defaults={},preload=()=>{},view=()=>"",edit=()=>"",onMount=()=>""}=opts;ContactFilterRegistry.registerFilter(createFilter(type,name,group,{display:view,preload:preload,edit:({updateFilter,...filter})=>Fragment([edit(filter)],{onCreate:el=>{setTimeout(()=>{onMount(filter,updateFilter)},50)}})},defaults))};const standardActivityDateFilterOnMount=(filter,updateFilter)=>{$("#filter-date-range, #filter-before, #filter-after, #filter-days").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()});if($el.prop("name")==="date_range"){const $before=$("#filter-before");const $after=$("#filter-after");const $days=$("#filter-days");$before.addClass("hidden");$after.addClass("hidden");$days.addClass("hidden");switch($el.val()){case"between":$before.removeClass("hidden");$after.removeClass("hidden");break;case"day_of":case"after":$after.removeClass("hidden");break;case"before":$before.removeClass("hidden");break;case"x_days":$days.removeClass("hidden");break}}})};const standardActivityDateTitle=(prepend,{date_range,before,after,days=0,future=false})=>{let ranges=future?futureDateRanges:pastDateRanges;switch(date_range){default:return`${prepend} ${ranges[date_range]?ranges[date_range].replace("X",days).toLowerCase():""}`;case"between":return`${prepend} ${sprintf(_x("between %1$s and %2$s","where %1 and %2 are dates","groundhogg"),`<b>${formatDate(after)}</b>`,`<b>${formatDate(before)}</b>`)}`;case"before":return`${prepend} ${sprintf(_x("before %s","%s is a date","groundhogg"),`<b>${formatDate(before)}</b>`)}`;case"after":return`${prepend} ${sprintf(_x("after %s","%s is a date","groundhogg"),`<b>${formatDate(after)}</b>`)}`;case"day_of":return`${prepend} ${sprintf(_x("on %s","%s is a date","groundhogg"),`<b>${formatDate(after)}</b>`)}`}};const standardActivityDateOptions=({date_range="24_hours",after="",before="",days=0,future=false})=>{return[select({id:"filter-date-range",name:"date_range"},future?futureDateRanges:pastDateRanges,date_range),input({type:"date",value:after.split(" ")[0],id:"filter-after",className:`date ${["between","after","day_of"].includes(date_range)?"":"hidden"}`,name:"after"}),input({type:"date",value:before.split(" ")[0],id:"filter-before",className:`value ${["between","before"].includes(date_range)?"":"hidden"}`,name:"before"}),input({type:"number",value:days,id:"filter-days",min:0,className:`value ${["x_days","next_x_days"].includes(date_range)?"":"hidden"}`,name:"days"})].join("")};const standardActivityDateDefaults={date_range:"any",before:"",after:"",count:1,days:0};const filterCountDefaults={count:1,count_compare:"greater_than_or_equal_to"};const activityFilterComparisons={equals:_x("Exactly","comparison","groundhogg"),less_than:_x("Less than","comparison","groundhogg"),greater_than:_x("More than","comparison","groundhogg"),less_than_or_equal_to:_x("At most","comparison","groundhogg"),greater_than_or_equal_to:_x("At least","comparison","groundhogg")};const filterCount=({count,count_compare})=>{return`
    22        <div class="space-between" style="gap: 10px">
    33            <div class="gh-input-group">
     
    88              ${__("Times")}
    99          </span>
    10         </div>`};const filterCountOnMount=updateFilter=>{$("#filter-count,#filter-count-compare").on("change",e=>{updateFilter({[e.target.name]:e.target.value})})};const filterCountComparisons={equals:v=>sprintf(_n("%s time","%s times",parseInt(v),"groundhogg"),v),less_than:v=>sprintf(_n("less than %s time","less than %s times",parseInt(v),"groundhogg"),v),less_than_or_equal_to:v=>sprintf(_n("at most %s time","at most %s times",parseInt(v),"groundhogg"),v),greater_than:v=>sprintf(_n("more than %s time","more than %s times",parseInt(v),"groundhogg"),v),greater_than_or_equal_to:v=>sprintf(_n("at least %s time","at least %s times",parseInt(v),"groundhogg"),v)};const filterCountTitle=(title,{count:count=1,count_compare:count_compare="equals"})=>{return title+" "+filterCountComparisons[count_compare](count)};const BasicTextFilter=name=>({name:name,view({compare,value}){return ComparisonsTitleGenerators[compare](`<b>${name}</b>`,`<b>"${value}"</b>`)},edit({compare,value}){return`${select({id:"filter-compare",name:"compare"},StringComparisons,compare)} ${input({id:"filter-value",name:"value",value:value})}`},onMount(filter,updateFilter){$("#filter-compare, #filter-value").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"equals",value:""}});registerFilterGroup("contact",_x("Contact","noun referring to a person in the crm","groundhogg"));registerFilterGroup("location",_x("Contact Location","contact is a noun referring to a person","groundhogg"));registerFilterGroup("user",__("User"));registerFilterGroup("activity",_x("Activity","noun referring to a persons past activities","groundhogg"));registerFilter("first_name","contact",{...BasicTextFilter(__("First Name","groundhogg"))});registerFilter("last_name","contact",{...BasicTextFilter(__("Last Name","groundhogg"))});registerFilter("email","contact",{...BasicTextFilter(__("Email Address","groundhogg"))});const phoneTypes={primary:__("Primary Phone","groundhogg"),mobile:__("Mobile Phone","groundhogg"),company:__("Company Phone","groundhogg")};registerFilter("phone","contact",{name:__("Phone Number","groundhogg"),view({phone_type:phone_type="primary",compare,value}){return ComparisonsTitleGenerators[compare](`<b>${phoneTypes[phone_type]}</b>`,`<b>"${value}"</b>`)},edit({phone_type,compare,value}){return`${select({id:"filter-phone-type",name:"phone_type"},phoneTypes,phone_type)}
     10        </div>`};const filterCountOnMount=updateFilter=>{$("#filter-count,#filter-count-compare").on("change",e=>{updateFilter({[e.target.name]:e.target.value})})};const filterCountComparisons={equals:v=>sprintf(_n("%s time","%s times",parseInt(v),"groundhogg"),v),less_than:v=>sprintf(_n("less than %s time","less than %s times",parseInt(v),"groundhogg"),v),less_than_or_equal_to:v=>sprintf(_n("at most %s time","at most %s times",parseInt(v),"groundhogg"),v),greater_than:v=>sprintf(_n("more than %s time","more than %s times",parseInt(v),"groundhogg"),v),greater_than_or_equal_to:v=>sprintf(_n("at least %s time","at least %s times",parseInt(v),"groundhogg"),v)};const filterCountTitle=(title,{count=1,count_compare="equals"})=>{return title+" "+filterCountComparisons[count_compare](count)};const BasicTextFilter=name=>({name:name,view({compare,value}){return ComparisonsTitleGenerators[compare](`<b>${name}</b>`,`<b>"${value}"</b>`)},edit({compare,value}){return`${select({id:"filter-compare",name:"compare"},StringComparisons,compare)} ${input({id:"filter-value",name:"value",value:value})}`},onMount(filter,updateFilter){$("#filter-compare, #filter-value").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"equals",value:""}});registerFilterGroup("contact",_x("Contact","noun referring to a person in the crm","groundhogg"));registerFilterGroup("location",_x("Contact Location","contact is a noun referring to a person","groundhogg"));registerFilterGroup("user",__("User"));registerFilterGroup("activity",_x("Activity","noun referring to a persons past activities","groundhogg"));registerFilter("first_name","contact",{...BasicTextFilter(__("First Name","groundhogg"))});registerFilter("last_name","contact",{...BasicTextFilter(__("Last Name","groundhogg"))});registerFilter("email","contact",{...BasicTextFilter(__("Email Address","groundhogg"))});const phoneTypes={primary:__("Primary Phone","groundhogg"),mobile:__("Mobile Phone","groundhogg"),company:__("Company Phone","groundhogg")};registerFilter("phone","contact",{name:__("Phone Number","groundhogg"),view({phone_type="primary",compare,value}){return ComparisonsTitleGenerators[compare](`<b>${phoneTypes[phone_type]}</b>`,`<b>"${value}"</b>`)},edit({phone_type,compare,value}){return`${select({id:"filter-phone-type",name:"phone_type"},phoneTypes,phone_type)}
    1111      ${select({id:"filter-compare",name:"compare"},StringComparisons,compare)} ${input({id:"filter-value",name:"value",value:value})}`},onMount(filter,updateFilter){$("#filter-phone-type, #filter-compare, #filter-value").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{phone_type:"primary",compare:"equals",value:""}});ContactFilterRegistry.registerFilter(createDateFilter("birthday",__("Birthday","groundhogg"),"contact"));ContactFilterRegistry.registerFilter(createNumberFilter("age",__("Age","groundhogg"),"contact"));ContactFilterRegistry.registerFilter(createPastDateFilter("date_created",__("Date Created","groundhogg"),"contact"));const{optin_status,owners,countries,roles}=Groundhogg.filters;registerFilter("optin_status","contact",__("Opt-in Status","groundhogg"),{view({compare,value}){const func=compare==="in"?orList:andList;return ComparisonsTitleGenerators[compare](`<b>${__("Opt-in Status","groundhogg")}</b>`,func(value.map(v=>`<b>${optin_status[v]}</b>`)))},edit({compare,value}){return`
    1212          ${select({id:"filter-compare",name:"compare",class:""},{in:_x("Is one of","comparison, groundhogg"),not_in:_x("Is not one of","comparison","groundhogg")},compare)}
    1313          ${select({id:"filter-value",name:"value",class:"gh-select2",multiple:true},Object.keys(optin_status).map(k=>({value:k,text:optin_status[k]})),value)} `},onMount(filter,updateFilter){$("#filter-value").select2();$("#filter-value, #filter-compare").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"in",value:[]}});registerFilter("is_marketable","contact",__("Marketable","groundhogg"),{view({marketable}){return marketable==="yes"?__("Is marketable","groundhogg"):__("Is not marketable","groundhogg")},edit({marketable}){return`
    14           ${select({id:"filter-marketable",name:"marketable"},{yes:_x("Yes","comparison, groundhogg"),no:_x("No","comparison","groundhogg")},marketable)}`},onMount(filter,updateFilter){$("#filter-marketable").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{marketable:"yes"}});const userDisplay=user=>{return`${user.data.display_name} (${user.data.user_email})`};registerFilter("owner","contact",__("Owner","groundhogg"),{view({compare,value:value=[]}){if(!value.length){throw new Error("At least 1 owner must be selected.")}const ownerName=ID=>{let user=owners.find(owner=>owner.ID==ID);if(!user){throw new Error(`Owner with ID ${ID} does not exist`)}return userDisplay(user)};const func=compare==="in"?orList:andList;return ComparisonsTitleGenerators[compare](`<b>${__("Contact Owner","groundhogg")}</b>`,func(value.map(v=>`<b>${ownerName(v)}</b>`)))},edit({compare,value}){return`
     14          ${select({id:"filter-marketable",name:"marketable"},{yes:_x("Yes","comparison, groundhogg"),no:_x("No","comparison","groundhogg")},marketable)}`},onMount(filter,updateFilter){$("#filter-marketable").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{marketable:"yes"}});const userDisplay=user=>{return`${user.data.display_name} (${user.data.user_email})`};registerFilter("owner","contact",__("Owner","groundhogg"),{view({compare,value=[]}){if(!value.length){throw new Error("At least 1 owner must be selected.")}const ownerName=ID=>{let user=owners.find(owner=>owner.ID==ID);if(!user){throw new Error(`Owner with ID ${ID} does not exist`)}return userDisplay(user)};const func=compare==="in"?orList:andList;return ComparisonsTitleGenerators[compare](`<b>${__("Contact Owner","groundhogg")}</b>`,func(value.map(v=>`<b>${ownerName(v)}</b>`)))},edit({compare,value}){return`
    1515          ${select({id:"filter-compare",name:"compare"},{in:_x("Is one of","comparison, groundhogg"),not_in:_x("Is not one of","comparison","groundhogg")},compare)}
    1616
    17           ${select({id:"filter-value",name:"value",multiple:true},owners.map(u=>({value:u.ID,text:userDisplay(u)})),value.map(id=>parseInt(id)))} `},onMount(filter,updateFilter){$("#filter-value").select2();$("#filter-value, #filter-compare").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"in",value:[]}});registerFilter("tags","contact",_x("Tags","noun referring to contact segments","groundhogg"),{view({tags:tags=[],compare,compare2}){if(!tags){return"tags"}tags=tags.map(t=>{let tag=TagsStore.get(parseInt(t));if(!tag){throw new Error(`Tag of ID ${t} does not exist`)}return tag});const tagNames=tags.map(t=>`<b>${t.data.tag_name}</b>`);const func=compare2==="any"?orList:andList;return ComparisonsTitleGenerators[compare](`<b>${_x("Tags","noun referring to contact segments","groundhogg")}</b>`,func(tagNames))},edit({tags,compare,compare2}){tags=tags.map(t=>TagsStore.get(parseInt(t))).filter(Boolean);return`${select({id:"filter-compare",name:"compare"},{includes:_x("Includes","comparison","groundhogg"),excludes:_x("Excludes","comparison","groundhogg")},compare)}
     17          ${select({id:"filter-value",name:"value",multiple:true},owners.map(u=>({value:u.ID,text:userDisplay(u)})),value.map(id=>parseInt(id)))} `},onMount(filter,updateFilter){$("#filter-value").select2();$("#filter-value, #filter-compare").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"in",value:[]}});registerFilter("tags","contact",_x("Tags","noun referring to contact segments","groundhogg"),{view({tags=[],compare,compare2}){if(!tags){return"tags"}tags=tags.map(t=>{let tag=TagsStore.get(parseInt(t));if(!tag){throw new Error(`Tag of ID ${t} does not exist`)}return tag});const tagNames=tags.map(t=>`<b>${t.data.tag_name}</b>`);const func=compare2==="any"?orList:andList;return ComparisonsTitleGenerators[compare](`<b>${_x("Tags","noun referring to contact segments","groundhogg")}</b>`,func(tagNames))},edit({tags,compare,compare2}){tags=tags.map(t=>TagsStore.get(parseInt(t))).filter(Boolean);return`${select({id:"filter-compare",name:"compare"},{includes:_x("Includes","comparison","groundhogg"),excludes:_x("Excludes","comparison","groundhogg")},compare)}
    1818
    1919        ${select({id:"filter-compare2",name:"compare2"},{any:__("Any","groundhogg"),all:__("All","groundhogg")},compare2)}
    2020
    2121        ${select({id:"filter-tags",name:"tags",className:"tag-picker",multiple:true},tags.map(t=>({value:t.ID,text:t.data.tag_name})),tags.map(t=>t.ID))}`},onMount(filter,updateFilter){tagPicker("#filter-tags",true,items=>{TagsStore.itemsFetched(items)},{tags:false}).on("change",e=>{updateFilter({tags:$(e.target).val()})});$("#filter-compare, #filter-compare2").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"includes",compare2:"any",tags:[]},preload:({tags})=>{if(!TagsStore.hasItems(tags)){return TagsStore.fetchItems({tag_id:tags})}}});registerFilter("meta","contact",__("Custom meta","groundhogg"),{view({meta,compare,value}){return ComparisonsTitleGenerators[compare](`<b>${meta}</b>`,`<b>"${value}"</b>`)},edit({meta,compare,value},filterGroupIndex,filterIndex){return[input({id:"filter-meta",name:"meta",className:"meta-picker",dataGroup:filterIndex,dataKey:filterIndex,value:meta}),select({id:"filter-compare",name:"compare",dataGroup:filterIndex,dataKey:filterIndex},AllComparisons,compare),["empty","not_empty"].includes(compare)?"":input({id:"filter-value",name:"value",dataGroup:filterIndex,dataKey:filterIndex,value:value})].join("")},onMount(filter,updateFilter){metaPicker("#filter-meta");$("#filter-compare, #filter-value, #filter-meta").on("change blur",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()},true)})},defaults:{meta:"",compare:"equals",value:""}});registerFilter("contact_id","contact",__("Contact ID","groundhogg"),{view({compare,value}){return ComparisonsTitleGenerators[compare](`<b>${__("Contact ID")}</b>`,`<b>${value}</b>`)},edit({compare,value}){return`
    22           ${select({id:"filter-compare",name:"compare"},NumericComparisons,compare)} ${input({id:"filter-value",name:"value",type:"number",step:"0.01",value:value})}`},onMount(filter,updateFilter){$("#filter-compare, #filter-value").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"equals",value:""}});registerFilter("is_user","user",__("Has User Account","groundhogg"),{view(){return __("Has a user account","groundhogg")},edit(){return""},onMount(filter,updateFilter){},defaults:{}});registerFilter("user_role_is","user",__("User Role","groundhogg"),{view({role:role="subscriber"}){return sprintf(__("User role is %s","groundhogg"),bold(role?roles[role].name:""))},edit({role}){return`${select({id:"filter-role",name:"role"},Object.keys(roles).map(r=>({text:roles[r].name,value:r})),role)}`},onMount(filter,updateFilter){$("#filter-role").select2({placeholder:__("Select a role","groundhogg")}).on("change",function(e){const $el=$(this);updateFilter({role:$el.val()})})},defaults:{role:"subscriber"}});registerFilter("user_meta","user",__("User Meta","groundhogg"),{view({meta,compare,value}){return ComparisonsTitleGenerators[compare](`<b>${meta}</b>`,`<b>"${value}"</b>`)},edit({meta,compare,value},filterGroupIndex,filterIndex){return`
     22          ${select({id:"filter-compare",name:"compare"},NumericComparisons,compare)} ${input({id:"filter-value",name:"value",type:"number",step:"0.01",value:value})}`},onMount(filter,updateFilter){$("#filter-compare, #filter-value").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"equals",value:""}});registerFilter("is_user","user",__("Has User Account","groundhogg"),{view(){return __("Has a user account","groundhogg")},edit(){return""},onMount(filter,updateFilter){},defaults:{}});registerFilter("user_role_is","user",__("User Role","groundhogg"),{view({role="subscriber"}){return sprintf(__("User role is %s","groundhogg"),bold(role?roles[role].name:""))},edit({role}){return`${select({id:"filter-role",name:"role"},Object.keys(roles).map(r=>({text:roles[r].name,value:r})),role)}`},onMount(filter,updateFilter){$("#filter-role").select2({placeholder:__("Select a role","groundhogg")}).on("change",function(e){const $el=$(this);updateFilter({role:$el.val()})})},defaults:{role:"subscriber"}});registerFilter("user_meta","user",__("User Meta","groundhogg"),{view({meta,compare,value}){return ComparisonsTitleGenerators[compare](`<b>${meta}</b>`,`<b>"${value}"</b>`)},edit({meta,compare,value},filterGroupIndex,filterIndex){return`
    2323          ${input({id:"filter-meta",name:"meta",className:"meta-picker",dataGroup:filterIndex,dataKey:filterIndex,value:meta})}
    2424          ${select({id:"filter-compare",name:"compare",dataGroup:filterIndex,dataKey:filterIndex},AllComparisons,compare)} ${input({id:"filter-value",name:"value",dataGroup:filterIndex,dataKey:filterIndex,value:value})}`},onMount(filter,updateFilter){userMetaPicker("#filter-meta");$("#filter-compare, #filter-value, #filter-meta").on("change blur",function(e){const $el=$(this);const{compare}=updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{meta:"",compare:"equals",value:""}});registerFilter("user_id","user",__("User ID","groundhogg"),{view({compare,value}){return ComparisonsTitleGenerators[compare](`<b>${__("User ID")}</b>`,`<b>${value}</b>`)},edit({compare,value}){return`
     
    2626          ${select({id:"filter-country",name:"country"},countries,country)}`},onMount(filter,updateFilter){$("#filter-country").select2().on("change",function(e){const $el=$(this);updateFilter({country:$el.val()})})},defaults:{country:""}});registerFilter("region","location",__("State/Province","groundhogg"),{view({region}){return sprintf(__("State/Province is %s","groundhogg"),bold(region))},edit({region}){return`
    2727          ${input({id:"filter-region",name:"region",value:region,autocomplete:"off",placeholder:__("Start typing to select a region","groundhogg")})}`},onMount(filter,updateFilter){metaValuePicker("#filter-region","region").on("change blur",function(e){updateFilter({region:$(e.target).val()})})},defaults:{region:""}});registerFilter("city","location",__("City","groundhogg"),{view({city}){return sprintf(__("City is %s","groundhogg"),bold(city))},edit({city}){return`
    28           ${input({id:"filter-city",name:"city",value:city,autocomplete:"off",placeholder:__("Start typing to select a city","groundhogg")})}`},onMount(filter,updateFilter){metaValuePicker("#filter-city","city").on("change blur",function(e){updateFilter({city:$(e.target).val()})})},defaults:{city:""}});registerFilter("street_address_1","location",__("Line 1","groundhogg"),{...BasicTextFilter(__("Street Address 1","groundhogg"))});registerFilter("street_address_2","location",__("Line 2","groundhogg"),{...BasicTextFilter(__("Street Address 2","groundhogg"))});registerFilter("zip_code","location",__("Zip/Postal Code","groundhogg"),{...BasicTextFilter(__("Zip/Postal Code","groundhogg"))});registerFilter("locale","location",__("Locale","groundhogg"),{view({locales:locales=[]}){if(!locales.length){throw new Error("Select a locale")}let dropdown=Div({},GroundhoggLocalDropdown).firstElementChild;locales=locales.map(locale=>bold(dropdown.querySelector(`option[value="${locale}"]`).innerHTML));return sprintf("%s is %s",bold(__("Locale")),orList(locales))},edit({locales:locales=[]}){let dropdown=Div({},GroundhoggLocalDropdown).firstElementChild;dropdown.multiple=true;locales.forEach(locale=>{dropdown.querySelector(`option[value="${locale}"]`).selected=true});return dropdown},onMount(filter,updateFilter){$("#filter-locale").select2({multiple:true}).on("change",function(e){const $el=$(this);updateFilter({locales:$el.val()})})},defaults:{locales:["en_US"]}});registerFilter("email_received","activity",__("Email Received","groundhogg"),{view({email_id,...rest}){const emailName=email_id?EmailsStore.get(email_id).data.title:"any email";let prefix=sprintf(_x("Received %s","%s is an email","groundhogg"),`<b>${emailName}</b>`);prefix=filterCountTitle(prefix,rest);return standardActivityDateTitle(prefix,rest)},edit({email_id,...rest}){const pickerOptions=email_id?{[email_id]:EmailsStore.get(email_id).data.title}:{};return`
     28          ${input({id:"filter-city",name:"city",value:city,autocomplete:"off",placeholder:__("Start typing to select a city","groundhogg")})}`},onMount(filter,updateFilter){metaValuePicker("#filter-city","city").on("change blur",function(e){updateFilter({city:$(e.target).val()})})},defaults:{city:""}});registerFilter("street_address_1","location",__("Line 1","groundhogg"),{...BasicTextFilter(__("Street Address 1","groundhogg"))});registerFilter("street_address_2","location",__("Line 2","groundhogg"),{...BasicTextFilter(__("Street Address 2","groundhogg"))});registerFilter("zip_code","location",__("Zip/Postal Code","groundhogg"),{...BasicTextFilter(__("Zip/Postal Code","groundhogg"))});registerFilter("locale","location",__("Locale","groundhogg"),{view({locales=[]}){if(!locales.length){throw new Error("Select a locale")}let dropdown=Div({},GroundhoggLocalDropdown).firstElementChild;locales=locales.map(locale=>bold(dropdown.querySelector(`option[value="${locale}"]`).innerHTML));return sprintf("%s is %s",bold(__("Locale")),orList(locales))},edit({locales=[]}){let dropdown=Div({},GroundhoggLocalDropdown).firstElementChild;dropdown.multiple=true;locales.forEach(locale=>{dropdown.querySelector(`option[value="${locale}"]`).selected=true});return dropdown},onMount(filter,updateFilter){$("#filter-locale").select2({multiple:true}).on("change",function(e){const $el=$(this);updateFilter({locales:$el.val()})})},defaults:{locales:["en_US"]}});registerFilter("email_received","activity",__("Email Received","groundhogg"),{view({email_id,...rest}){const emailName=email_id?EmailsStore.get(email_id).data.title:"any email";let prefix=sprintf(_x("Received %s","%s is an email","groundhogg"),`<b>${emailName}</b>`);prefix=filterCountTitle(prefix,rest);return standardActivityDateTitle(prefix,rest)},edit({email_id,...rest}){const pickerOptions=email_id?{[email_id]:EmailsStore.get(email_id).data.title}:{};return`
    2929            ${select({id:"filter-email",name:"email_id"},pickerOptions,email_id)}
    3030
     
    3636          ${filterCount(rest)}
    3737
    38           ${standardActivityDateOptions(rest)}`},onMount(filter,updateFilter){emailPicker("#filter-email",false,items=>{EmailsStore.itemsFetched(items)},{},{placeholder:__("Please select an email or leave blank for any email","groundhogg")}).on("change",e=>{updateFilter({email_id:parseInt(e.target.value)})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults,email_id:0},preload:({email_id})=>{if(email_id){return EmailsStore.maybeFetchItem(email_id)}}});registerFilter("email_link_clicked","activity",__("Email Link Clicked","groundhogg"),{view({email_id,link:link="",...rest}){const emailName=email_id?EmailsStore.get(email_id).data.title:"any email";const maybeTruncateLink=link=>{return link.length>50?`${link.substring(0,47)}...`:link};let prepend=sprintf(link?__("Clicked %1$s in %2$s","groundhogg"):__("Clicked any link in %2$s","groundhogg"),`<b class="link" title="${link}">${maybeTruncateLink(link)}</b>`,`<b>${emailName}</b>`);prepend=filterCountTitle(prepend,rest);return standardActivityDateTitle(prepend,rest)},edit({email_id,link,...rest}){const pickerOptions=email_id?{[email_id]:EmailsStore.get(email_id).data.title}:{};return`
     38          ${standardActivityDateOptions(rest)}`},onMount(filter,updateFilter){emailPicker("#filter-email",false,items=>{EmailsStore.itemsFetched(items)},{},{placeholder:__("Please select an email or leave blank for any email","groundhogg")}).on("change",e=>{updateFilter({email_id:parseInt(e.target.value)})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults,email_id:0},preload:({email_id})=>{if(email_id){return EmailsStore.maybeFetchItem(email_id)}}});registerFilter("email_link_clicked","activity",__("Email Link Clicked","groundhogg"),{view({email_id,link="",...rest}){const emailName=email_id?EmailsStore.get(email_id).data.title:"any email";const maybeTruncateLink=link=>{return link.length>50?`${link.substring(0,47)}...`:link};let prepend=sprintf(link?__("Clicked %1$s in %2$s","groundhogg"):__("Clicked any link in %2$s","groundhogg"),`<b class="link" title="${link}">${maybeTruncateLink(link)}</b>`,`<b>${emailName}</b>`);prepend=filterCountTitle(prepend,rest);return standardActivityDateTitle(prepend,rest)},edit({email_id,link,...rest}){const pickerOptions=email_id?{[email_id]:EmailsStore.get(email_id).data.title}:{};return`
    3939            ${select({id:"filter-email",name:"email_id"},pickerOptions,email_id)}
    4040
     
    4343            ${filterCount(rest)}
    4444
    45             ${standardActivityDateOptions(rest)}`},onMount(filter,updateFilter){emailPicker("#filter-email",false,items=>{EmailsStore.itemsFetched(items)},{},{placeholder:__("Please select an email or leave blank for any email","groundhogg")}).on("change",e=>{updateFilter({email_id:parseInt(e.target.value)})});linkPicker("#filter-link").on("change input blur",({target})=>{updateFilter({link:target.value})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults,link:"",email_id:0},preload:({email_id})=>{if(email_id){return EmailsStore.maybeFetchItem(email_id)}}});registerFilter("confirmed_email","activity",__("Confirmed Email Address","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Confirmed Email Address","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});ContactFilterRegistry.registerFilter(createPastDateFilter("unsubscribed",__("Unsubscribed","groundhogg"),"activity",{edit:({reasons:reasons=[],updateFilter})=>Fragment([ItemPicker({id:"unsub-reasons",placeholder:__("Search","groundhogg"),noneSelected:__("Any reason","groundhogg"),fetchOptions:async s=>assoc2array(unsubReasons),selected:reasons.map(reason=>({id:reason,text:unsubReasons[reason]??reason})),onChange:items=>{let reasons=items.map(({id})=>id);console.log(reasons);updateFilter({reasons:reasons})}})]),display:({reasons:reasons=[]})=>sprintf("Unsubscribed %s",orList(reasons.map(r=>bold(unsubReasons[r]??r))))}));registerFilter("optin_status_changed","activity",__("Opt-in Status Changed","groundhogg"),{view({value,...filter}){return standardActivityDateTitle(sprintf("<b>Opt-in status</b> changed to %s",orList(value.map(v=>`<b>${optin_status[v]}</b>`))),filter)},edit({value,...filter}){return[select({id:"filter-value",name:"value",class:"gh-select2",multiple:true},Object.keys(optin_status).map(k=>({value:k,text:optin_status[k]})),value),standardActivityDateOptions(filter)].join("")},onMount(filter,updateFilter){$("#filter-value").select2();$("#filter-value").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})});standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{value:[],...standardActivityDateDefaults}});registerFilter("page_visited","activity",__("Page Visited","groundhogg"),{view({link,...rest}){let prefix;if(link){const url=new URL(link);prefix=sprintf(__("Visited %s","groundhogg"),bold(url.pathname))}else{prefix=__("Visited <b>any page</b>","groundhogg")}prefix=filterCountTitle(prefix,rest);return standardActivityDateTitle(prefix,rest)},edit({link,...rest}){return`
     45            ${standardActivityDateOptions(rest)}`},onMount(filter,updateFilter){emailPicker("#filter-email",false,items=>{EmailsStore.itemsFetched(items)},{},{placeholder:__("Please select an email or leave blank for any email","groundhogg")}).on("change",e=>{updateFilter({email_id:parseInt(e.target.value)})});linkPicker("#filter-link").on("change input blur",({target})=>{updateFilter({link:target.value})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults,link:"",email_id:0},preload:({email_id})=>{if(email_id){return EmailsStore.maybeFetchItem(email_id)}}});registerFilter("confirmed_email","activity",__("Confirmed Email Address","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Confirmed Email Address","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});ContactFilterRegistry.registerFilter(createPastDateFilter("unsubscribed",__("Unsubscribed","groundhogg"),"activity",{edit:({reasons=[],updateFilter})=>Fragment([ItemPicker({id:"unsub-reasons",placeholder:__("Search","groundhogg"),noneSelected:__("Any reason","groundhogg"),fetchOptions:async s=>assoc2array(unsubReasons),selected:reasons.map(reason=>({id:reason,text:unsubReasons[reason]??reason})),onChange:items=>{let reasons=items.map(({id})=>id);console.log(reasons);updateFilter({reasons:reasons})}})]),display:({reasons=[]})=>sprintf("Unsubscribed %s",orList(reasons.map(r=>bold(unsubReasons[r]??r))))}));registerFilter("optin_status_changed","activity",__("Opt-in Status Changed","groundhogg"),{view({value,...filter}){return standardActivityDateTitle(sprintf("<b>Opt-in status</b> changed to %s",orList(value.map(v=>`<b>${optin_status[v]}</b>`))),filter)},edit({value,...filter}){return[select({id:"filter-value",name:"value",class:"gh-select2",multiple:true},Object.keys(optin_status).map(k=>({value:k,text:optin_status[k]})),value),standardActivityDateOptions(filter)].join("")},onMount(filter,updateFilter){$("#filter-value").select2();$("#filter-value").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})});standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{value:[],...standardActivityDateDefaults}});registerFilter("page_visited","activity",__("Page Visited","groundhogg"),{view({link,...rest}){let prefix;if(link){const url=new URL(link);prefix=sprintf(__("Visited %s","groundhogg"),bold(url.pathname))}else{prefix=__("Visited <b>any page</b>","groundhogg")}prefix=filterCountTitle(prefix,rest);return standardActivityDateTitle(prefix,rest)},edit({link,...rest}){return`
    4646
    4747          ${input({id:"filter-link",name:"link",autocomplete:"off",value:link,placeholder:__("Start typing to select a link or leave blank for any link","groundhogg")})}
     
    4949          ${filterCount(rest)}
    5050
    51           ${standardActivityDateOptions(rest)}`},onMount(filter,updateFilter){linkPicker("#filter-link").on("change input blur",({target})=>{updateFilter({link:target.value})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults,link:""}});registerFilter("logged_in","activity",__("Logged In","groundhogg"),{view(filter){let prefix=filterCountTitle(`<b>${__("Logged in","groundhogg")}</b>`,filter);return standardActivityDateTitle(prefix,filter)},edit(filter){return filterCount(filter)+standardActivityDateOptions(filter)},onMount(filter,updateFilter){filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults}});registerFilter("logged_out","activity",__("Logged Out","groundhogg"),{view(filter){return standardActivityDateTitle(filterCountTitle(`<b>${__("Logged out","groundhogg")}</b>`,filter),filter)},edit(filter){return filterCount(filter)+standardActivityDateOptions(filter)},onMount(filter,updateFilter){filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...filterCountDefaults,...standardActivityDateDefaults}});registerFilter("not_logged_in","activity",__("Has Not Logged In","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Has not logged in","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});registerFilter("was_active","activity",__("Was Active","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Was active","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});registerFilter("was_not_active","activity",__("Was Inactive","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Was inactive","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});registerFilterGroup("funnels",_x("Flows","noun meaning automation","groundhogg"));registerFilter("funnel_history","funnels",__("Flow History","groundhogg"),{view({status:status="complete",funnel_id:funnel_id=0,step_id:step_id=0,date_range:date_range="any",before,after,...rest}){let prepend;if(funnel_id){const funnel=FunnelsStore.get(funnel_id);const step=funnel.steps.find(s=>s.ID===step_id);prepend=status==="complete"?sprintf(step?__("Completed %2$s in %1$s","groundhogg"):__("Completed any step in %1$s","groundhogg"),`<b>${funnel.data.title}</b>`,step?`<b>${step.data.step_title}</b>`:""):sprintf(step?__("Will complete %2$s in %1$s","groundhogg"):__("Will complete any step in %1$s","groundhogg"),`<b>${funnel.data.title}</b>`,step?`<b>${step.data.step_title}</b>`:"");if(status==="waiting"){return prepend}}else{prepend=__("Completed any step in any flow","groundhogg")}return standardActivityDateTitle(prepend,{date_range:date_range,before:before,after:after,...rest})},edit({funnel_id,step_id,date_range,before,after,...rest}){return`
     51          ${standardActivityDateOptions(rest)}`},onMount(filter,updateFilter){linkPicker("#filter-link").on("change input blur",({target})=>{updateFilter({link:target.value})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults,link:""}});registerFilter("logged_in","activity",__("Logged In","groundhogg"),{view(filter){let prefix=filterCountTitle(`<b>${__("Logged in","groundhogg")}</b>`,filter);return standardActivityDateTitle(prefix,filter)},edit(filter){return filterCount(filter)+standardActivityDateOptions(filter)},onMount(filter,updateFilter){filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults}});registerFilter("logged_out","activity",__("Logged Out","groundhogg"),{view(filter){return standardActivityDateTitle(filterCountTitle(`<b>${__("Logged out","groundhogg")}</b>`,filter),filter)},edit(filter){return filterCount(filter)+standardActivityDateOptions(filter)},onMount(filter,updateFilter){filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...filterCountDefaults,...standardActivityDateDefaults}});registerFilter("not_logged_in","activity",__("Has Not Logged In","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Has not logged in","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});registerFilter("was_active","activity",__("Was Active","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Was active","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});registerFilter("was_not_active","activity",__("Was Inactive","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Was inactive","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});registerFilterGroup("funnels",_x("Flows","noun meaning automation","groundhogg"));registerFilter("funnel_history","funnels",__("Flow History","groundhogg"),{view({status="complete",funnel_id=0,step_id=0,date_range="any",before,after,...rest}){let prepend;if(funnel_id){const funnel=FunnelsStore.get(funnel_id);const step=funnel.steps.find(s=>s.ID===step_id);prepend=status==="complete"?sprintf(step?__("Completed %2$s in %1$s","groundhogg"):__("Completed any step in %1$s","groundhogg"),`<b>${funnel.data.title}</b>`,step?`<b>${step.data.step_title}</b>`:""):sprintf(step?__("Will complete %2$s in %1$s","groundhogg"):__("Will complete any step in %1$s","groundhogg"),`<b>${funnel.data.title}</b>`,step?`<b>${step.data.step_title}</b>`:"");if(status==="waiting"){return prepend}}else{prepend=__("Completed any step in any flow","groundhogg")}return standardActivityDateTitle(prepend,{date_range:date_range,before:before,after:after,...rest})},edit({funnel_id,step_id,date_range,before,after,...rest}){return`
    5252      ${select({id:"filter-funnel",name:"funnel_id"},FunnelsStore.getItems().map(f=>({value:f.ID,text:f.data.title})),funnel_id)}
    5353      ${select({id:"filter-step",name:"step_id"},funnel_id?FunnelsStore.get(funnel_id).steps.map(s=>({value:s.ID,text:s.data.step_title})):[],step_id)}
    54       ${standardActivityDateOptions({date_range:date_range,before:before,after:after,...rest})}`},onMount(filter,updateFilter){funnelPicker("#filter-funnel",false,items=>{FunnelsStore.itemsFetched(items)},{},{placeholder:__("Select a flow","groundhogg")}).on("select2:select",({target})=>{updateFilter({funnel_id:parseInt($(target).val()),step_id:0},true)});$("#filter-step").select2({placeholder:__("Select a step or leave empty for any step","groundhogg")}).on("select2:select",({target})=>{updateFilter({step_id:parseInt($(target).val())})});standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{funnel_id:0,step_id:0,status:"complete",...standardActivityDateDefaults},preload:({funnel_id})=>{if(funnel_id){return FunnelsStore.maybeFetchItem(funnel_id)}}});registerFilterGroup("broadcast",_x("Broadcast","noun meaning email blast","groundhogg"));registerFilter("broadcast_received","broadcast",__("Received Broadcast","groundhogg"),{view({broadcast_id,status:status="complete"}){if(!broadcast_id){return __("Received any broadcast","groundhogg")}const broadcast=BroadcastsStore.get(broadcast_id);return status==="complete"?sprintf(broadcast?__("Received %1$s on %2$s","groundhogg"):__("Will receive a broadcast","groundhogg"),`<b>${broadcast.object.data.title}</b>`,`<b>${formatDateTime(broadcast.data.send_time*1e3)}</b>`):sprintf(broadcast?__("Will receive %1$s on %2$s","groundhogg"):__("Received a broadcast","groundhogg"),`<b>${broadcast.object.data.title}</b>`,`<b>${formatDateTime(broadcast.data.send_time*1e3)}</b>`)},edit({broadcast_id}){return select({id:"filter-broadcast",name:"broadcast_id"},BroadcastsStore.getItems().map(b=>({value:b.ID,text:`${b.object.data.title} (${b.date_sent_pretty})`})),broadcast_id)},onMount(filter,updateFilter){broadcastPicker("#filter-broadcast",false,items=>{BroadcastsStore.itemsFetched(items)},{},{placeholder:__("Select a broadcast","groundhogg")}).on("select2:select",({target})=>{updateFilter({broadcast_id:parseInt($(target).val())})})},defaults:{broadcast_id:0,status:"complete"},preload:({broadcast_id})=>{if(broadcast_id){return BroadcastsStore.maybeFetchItem(broadcast_id)}}});registerFilter("broadcast_opened","broadcast",__("Opened Broadcast","groundhogg"),{view({broadcast_id}){if(!broadcast_id){return __("Opened any broadcast","groundhogg")}const broadcast=BroadcastsStore.get(broadcast_id);return sprintf(broadcast?__("Opened %1$s after %2$s","groundhogg"):__("Will receive a broadcast","groundhogg"),`<b>${broadcast.object.data.title}</b>`,`<b>${formatDateTime(broadcast.data.send_time*1e3)}</b>`)},edit({broadcast_id}){return select({id:"filter-broadcast",name:"broadcast_id"},BroadcastsStore.getItems().map(b=>({value:b.ID,text:`${b.object.data.title} (${b.date_sent_pretty})`})),broadcast_id)},onMount(filter,updateFilter){broadcastPicker("#filter-broadcast",false,items=>{BroadcastsStore.itemsFetched(items)},{},{placeholder:__("Select a broadcast","groundhogg")}).on("select2:select",({target})=>{updateFilter({broadcast_id:parseInt($(target).val())})})},defaults:{broadcast_id:0},preload:({broadcast_id})=>{if(broadcast_id){return BroadcastsStore.maybeFetchItem(broadcast_id)}}});registerFilter("broadcast_link_clicked","broadcast",__("Broadcast Link Clicked","groundhogg"),{view({broadcast_id,link}){if(!broadcast_id&&!link){return __("Clicked any link in any broadcast","groundhogg")}if(!broadcast_id&&link){return sprintf(__("Clicked %s in any broadcast","groundhogg"),bold(link))}const broadcast=BroadcastsStore.get(broadcast_id);if(broadcast_id&&!link){return sprintf(__("Clicked any link in %1$s after %2$s","groundhogg"),bold(broadcast.object.data.title),bold(formatDateTime(broadcast.data.send_time*1e3)))}return sprintf(__("Clicked %1$s in %2$s after %3$s","groundhogg"),bold(link),bold(broadcast.object.data.title),bold(formatDateTime(broadcast.data.send_time*1e3)))},edit({broadcast_id,link}){return`
     54      ${standardActivityDateOptions({date_range:date_range,before:before,after:after,...rest})}`},onMount(filter,updateFilter){funnelPicker("#filter-funnel",false,items=>{FunnelsStore.itemsFetched(items)},{},{placeholder:__("Select a flow","groundhogg")}).on("select2:select",({target})=>{updateFilter({funnel_id:parseInt($(target).val()),step_id:0},true)});$("#filter-step").select2({placeholder:__("Select a step or leave empty for any step","groundhogg")}).on("select2:select",({target})=>{updateFilter({step_id:parseInt($(target).val())})});standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{funnel_id:0,step_id:0,status:"complete",...standardActivityDateDefaults},preload:({funnel_id})=>{if(funnel_id){return FunnelsStore.maybeFetchItem(funnel_id)}}});registerFilterGroup("broadcast",_x("Broadcast","noun meaning email blast","groundhogg"));registerFilter("broadcast_received","broadcast",__("Received Broadcast","groundhogg"),{view({broadcast_id,status="complete"}){if(!broadcast_id){return __("Received any broadcast","groundhogg")}const broadcast=BroadcastsStore.get(broadcast_id);return status==="complete"?sprintf(broadcast?__("Received %1$s on %2$s","groundhogg"):__("Will receive a broadcast","groundhogg"),`<b>${broadcast.object.data.title}</b>`,`<b>${formatDateTime(broadcast.data.send_time*1e3)}</b>`):sprintf(broadcast?__("Will receive %1$s on %2$s","groundhogg"):__("Received a broadcast","groundhogg"),`<b>${broadcast.object.data.title}</b>`,`<b>${formatDateTime(broadcast.data.send_time*1e3)}</b>`)},edit({broadcast_id}){return select({id:"filter-broadcast",name:"broadcast_id"},BroadcastsStore.getItems().map(b=>({value:b.ID,text:`${b.object.data.title} (${b.date_sent_pretty})`})),broadcast_id)},onMount(filter,updateFilter){broadcastPicker("#filter-broadcast",false,items=>{BroadcastsStore.itemsFetched(items)},{},{placeholder:__("Select a broadcast","groundhogg")}).on("select2:select",({target})=>{updateFilter({broadcast_id:parseInt($(target).val())})})},defaults:{broadcast_id:0,status:"complete"},preload:({broadcast_id})=>{if(broadcast_id){return BroadcastsStore.maybeFetchItem(broadcast_id)}}});registerFilter("broadcast_opened","broadcast",__("Opened Broadcast","groundhogg"),{view({broadcast_id}){if(!broadcast_id){return __("Opened any broadcast","groundhogg")}const broadcast=BroadcastsStore.get(broadcast_id);return sprintf(broadcast?__("Opened %1$s after %2$s","groundhogg"):__("Will receive a broadcast","groundhogg"),`<b>${broadcast.object.data.title}</b>`,`<b>${formatDateTime(broadcast.data.send_time*1e3)}</b>`)},edit({broadcast_id}){return select({id:"filter-broadcast",name:"broadcast_id"},BroadcastsStore.getItems().map(b=>({value:b.ID,text:`${b.object.data.title} (${b.date_sent_pretty})`})),broadcast_id)},onMount(filter,updateFilter){broadcastPicker("#filter-broadcast",false,items=>{BroadcastsStore.itemsFetched(items)},{},{placeholder:__("Select a broadcast","groundhogg")}).on("select2:select",({target})=>{updateFilter({broadcast_id:parseInt($(target).val())})})},defaults:{broadcast_id:0},preload:({broadcast_id})=>{if(broadcast_id){return BroadcastsStore.maybeFetchItem(broadcast_id)}}});registerFilter("broadcast_link_clicked","broadcast",__("Broadcast Link Clicked","groundhogg"),{view({broadcast_id,link}){if(!broadcast_id&&!link){return __("Clicked any link in any broadcast","groundhogg")}if(!broadcast_id&&link){return sprintf(__("Clicked %s in any broadcast","groundhogg"),bold(link))}const broadcast=BroadcastsStore.get(broadcast_id);if(broadcast_id&&!link){return sprintf(__("Clicked any link in %1$s after %2$s","groundhogg"),bold(broadcast.object.data.title),bold(formatDateTime(broadcast.data.send_time*1e3)))}return sprintf(__("Clicked %1$s in %2$s after %3$s","groundhogg"),bold(link),bold(broadcast.object.data.title),bold(formatDateTime(broadcast.data.send_time*1e3)))},edit({broadcast_id,link}){return`
    5555            ${select({id:"filter-broadcast",name:"broadcast_id"},BroadcastsStore.getItems().map(b=>({value:b.ID,text:`${b.object.data.title} (${b.date_sent_pretty})`})),broadcast_id)}
    5656
    57             ${input({id:"filter-link",name:"link",value:link,autocomplete:"off",placeholder:__("Start typing to select a link or leave blank for any link","groundhogg")})}`},onMount(filter,updateFilter){broadcastPicker("#filter-broadcast",false,items=>{BroadcastsStore.itemsFetched(items)},{},{placeholder:__("Please select a broadcast or leave blank for any broadcast","groundhogg")}).on("change",e=>{updateFilter({broadcast_id:parseInt(e.target.value)})});linkPicker("#filter-link").on("change input blur",({target})=>{updateFilter({link:target.value})})},defaults:{link:"",broadcast_id:0},preload:({broadcast_id})=>{if(broadcast_id){return BroadcastsStore.maybeFetchItem(broadcast_id)}}});ContactFilterRegistry.registerFromProperties(Groundhogg.filters.gh_contact_custom_properties);const registerActivityFilter=(id,group,label,{view:view=()=>{},edit:edit=()=>{},onMount:onMount=()=>{},defaults:defaults={}})=>{registerFilter(id,group,label,{view(filter){return standardActivityDateTitle(filterCountTitle(view(filter),filter),filter)},edit(filter){return[edit(filter),filterCount(filter),standardActivityDateOptions(filter)].join("")},onMount(filter,updateFilter){onMount(filter,updateFilter);filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...defaults,...standardActivityDateDefaults,...filterCountDefaults}})};const registerActivityFilterWithValue=(id,group,label,{view:view=()=>{},edit:edit=()=>{},onMount:onMount=()=>{},defaults:defaults={},...rest})=>{registerFilter(id,group,label,{view(filter){let{value,value_compare}=filter;let content=view(filter);if(value&&value_compare){content+=` worth ${activityFilterComparisons[value_compare].toLowerCase()} ${value}`}return standardActivityDateTitle(filterCountTitle(content,filter),filter)},edit(filter){let{value,value_compare}=filter;return[edit(filter),`
     57            ${input({id:"filter-link",name:"link",value:link,autocomplete:"off",placeholder:__("Start typing to select a link or leave blank for any link","groundhogg")})}`},onMount(filter,updateFilter){broadcastPicker("#filter-broadcast",false,items=>{BroadcastsStore.itemsFetched(items)},{},{placeholder:__("Please select a broadcast or leave blank for any broadcast","groundhogg")}).on("change",e=>{updateFilter({broadcast_id:parseInt(e.target.value)})});linkPicker("#filter-link").on("change input blur",({target})=>{updateFilter({link:target.value})})},defaults:{link:"",broadcast_id:0},preload:({broadcast_id})=>{if(broadcast_id){return BroadcastsStore.maybeFetchItem(broadcast_id)}}});ContactFilterRegistry.registerFromProperties(Groundhogg.filters.gh_contact_custom_properties);const registerActivityFilter=(id,group,label,{view=()=>{},edit=()=>{},onMount=()=>{},defaults={}})=>{registerFilter(id,group,label,{view(filter){return standardActivityDateTitle(filterCountTitle(view(filter),filter),filter)},edit(filter){return[edit(filter),filterCount(filter),standardActivityDateOptions(filter)].join("")},onMount(filter,updateFilter){onMount(filter,updateFilter);filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...defaults,...standardActivityDateDefaults,...filterCountDefaults}})};const registerActivityFilterWithValue=(id,group,label,{view=()=>{},edit=()=>{},onMount=()=>{},defaults={},...rest})=>{registerFilter(id,group,label,{view(filter){let{value,value_compare}=filter;let content=view(filter);if(value&&value_compare){content+=` worth ${activityFilterComparisons[value_compare].toLowerCase()} ${value}`}return standardActivityDateTitle(filterCountTitle(content,filter),filter)},edit(filter){let{value,value_compare}=filter;return[edit(filter),`
    5858              <div class="space-between" style="gap: 10px">
    5959                  <span class="gh-text">Value</span>
     
    6363                  </div>
    6464              </div>
    65           `,filterCount(filter),standardActivityDateOptions(filter)].join("")},onMount(filter,updateFilter){onMount(filter,updateFilter);$("#filter-value,#filter-value-compare").on("change",e=>{updateFilter({[e.target.name]:e.target.value})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...defaults,...standardActivityDateDefaults,...filterCountDefaults,value:0,value_compare:"greater_than_or_equal_to"},...rest})};registerActivityFilterWithValue("custom_activity","activity",__("Custom Activity","groundhogg"),{view:({activity})=>`<b>${activity}</b>`,edit:({activity,...filter})=>{return[input({id:"filter-activity-type",name:"activity",value:activity,placeholder:"custom_activity"}),`<label>${__("Filter by activity meta","groundhogg")}</label>`,`<div id="custom-activity-meta-filters"></div>`].join("")},onMount(filter,updateFilter){$("#filter-activity-type").on("input",e=>{updateFilter({activity:e.target.value})});let{meta_filters:meta_filters=[]}=filter;inputRepeater("#custom-activity-meta-filters",{rows:meta_filters,cells:[props=>input({placeholder:"Key",className:"input",...props}),({value,...props})=>select({selected:value,options:AllComparisons,...props}),props=>input({placeholder:"Value",className:"input",...props})],addRow:()=>["","equals",""],onChange:rows=>{updateFilter({meta_filters:rows})}}).mount()},defaults:{activity:"",meta_filters:[]}});registerFilterGroup("query","Query");registerFilter("saved_search","query",__("Saved Search"),{view:({compare:compare="in",search})=>{return sprintf(__("Is %s search %s"),compare==="in"?"in":"not in",bold(SearchesStore.get(search)?.name))},edit:({compare})=>{return[select({name:"filter_compare",id:"filter-compare",options:{in:__("In"),not_in:__("Not in")},selected:compare}),select({name:"filter_search",id:"filter-search"})].join("")},onMount:({search},updateFilter)=>{SearchesStore.maybeFetchItems().then(items=>{$("#filter-search").select2({data:[{id:"",text:""},...items.map(({id,name})=>({id:id,text:name,selected:id===search}))],placeholder:__("Type to search...")}).on("change",e=>{updateFilter({search:e.target.value})})});$("#filter-compare").on("change",e=>{updateFilter({compare:e.target.value})})},defaults:{compare:"in",search:null},preload:({search})=>{if(!SearchesStore.hasItems()){return SearchesStore.fetchItems([])}}});ContactFilterRegistry.registerFilter(createFilter("sub_query","Sub Query","query",{display:({include_filters:include_filters=[],exclude_filters:exclude_filters=[]})=>{let texts=[ContactFilterRegistry.displayFilters(include_filters),ContactFilterRegistry.displayFilters(exclude_filters)];if(include_filters.length&&exclude_filters.length){return texts.join(' <abbr title="exclude">and exclude</abbr> ')}if(exclude_filters.length){return sprintf('<abbr title="exclude">Exclude</abbr> %s',texts[1])}if(include_filters.length){return texts[0]}throw new Error("No filters defined.")},edit:({include_filters:include_filters=[],exclude_filters:exclude_filters=[],updateFilter})=>{return Fragment([Div({className:"include-search-filters"},[Filters({id:"sub-query-filters",filters:include_filters,filterRegistry:ContactFilterRegistry,onChange:include_filters=>updateFilter({include_filters:include_filters})})]),Div({className:"exclude-search-filters"},[Filters({id:"sub-query-exclude-filters",filters:exclude_filters,filterRegistry:ContactFilterRegistry,onChange:exclude_filters=>updateFilter({exclude_filters:exclude_filters})})])])},preload:({include_filters:include_filters=[],exclude_filters:exclude_filters=[]})=>{return Promise.all([ContactFilterRegistry.preloadFilters(include_filters),ContactFilterRegistry.preloadFilters(exclude_filters)])}},{}));ContactFilterRegistry.registerFilter(createFilter("secondary_related","Is Child Of","query",{edit:({object_type:object_type="",object_id:object_id="",updateFilter})=>Fragment([Input({id:"object-type",name:"object_type",value:object_type,placeholder:"Parent Type",onInput:e=>{updateFilter({object_type:e.target.value})}}),Input({type:"number",id:"object-id",name:"object_id",value:object_id,placeholder:"Parent ID",min:0,onInput:e=>{updateFilter({object_id:e.target.value})}})]),display:({object_type,object_id})=>{if(!object_type){throw new Error("Type be defined")}if(!object_id){return`Is a child of ${object_type}`}return`Is a child of ${object_type} with ID ${object_id}`}},{object_type:"contact"}));ContactFilterRegistry.registerFilter(createFilter("primary_related","Is Parent Of","query",{edit:({object_type:object_type="",object_id:object_id="",updateFilter})=>Fragment([Input({id:"object-type",name:"object_type",value:object_type,placeholder:"Child Type",onInput:e=>{updateFilter({object_type:e.target.value})}}),Input({type:"number",id:"object-id",name:"object_id",value:object_id,placeholder:"Child ID",min:0,onInput:e=>{updateFilter({object_id:e.target.value})}})]),display:({object_type,object_id})=>{if(!object_type){throw new Error("Type must be defined")}if(!object_id){return`Is a parent of ${object_type}`}return`Is a parent of ${object_type} with ID ${object_id}`}},{object_type:"contact"}));registerFilterGroup("date","Date");const CurrentDateCompareFilterFactory=(id,name,type,formatter)=>createFilter(id,name,"date",{edit:({compare:compare="",after:after="",before:before="",updateFilter})=>Fragment([Select({id:"select-compare",selected:compare,options:{after:"After",before:"Before",between:"Between"},onChange:e=>{updateFilter({compare:e.target.value})}}),compare==="before"?null:Input({type:type,id:"after-date",name:"after_date",value:after,placeholder:"After...",onChange:e=>{updateFilter({after:e.target.value})}}),compare==="after"?null:Input({type:type,id:"before-date",name:"before_date",value:before,placeholder:"Before...",min:0,onInput:e=>{updateFilter({before:e.target.value})}})]),display:({compare:compare="",after,before})=>{let prefix=`<b>${name}</b>`;switch(compare){case"between":return ComparisonsTitleGenerators.between(prefix,formatter(after),formatter(before));case"after":return ComparisonsTitleGenerators.after(prefix,formatter(after));case"before":return ComparisonsTitleGenerators.before(prefix,formatter(before));default:throw new Error("Invalid date comparison.")}}},{compare:"between",before:"",after:""});ContactFilterRegistry.registerFilter(CurrentDateCompareFilterFactory("current_datetime","Current Date & Time","datetime-local",formatDateTime));ContactFilterRegistry.registerFilter(CurrentDateCompareFilterFactory("current_date","Current Date","date",formatDate));ContactFilterRegistry.registerFilter(CurrentDateCompareFilterFactory("current_time","Current Time","time",time=>formatTime(`2000-01-01T${time}`)));registerFilterGroup("submissions","Submissions");const SubmissionMetaFilters=(meta_filters,updateFilter)=>InputRepeater({id:"submission-meta-filters",rows:meta_filters,cells:[props=>Input({...props,placeholder:"Field Name"}),({value,...props})=>Select({selected:value,options:AllComparisons,...props}),props=>Input({...props,placeholder:"Value"})],fillRow:()=>["","equals",""],onChange:rows=>{updateFilter({meta_filters:rows})}});ContactFilterRegistry.registerFilter(createPastDateFilter("form_submissions","Form Submissions","submissions",{display:({form_id:form_id=[]})=>{if(!form_id.length){return"Submitted any form"}return`Submitted ${orList(form_id.map(id=>bold(Groundhogg.stores.forms.get(id).name)))}`},preload:({form_id:form_id=[]})=>{if(form_id.length){return Groundhogg.stores.forms.maybeFetchItems(form_id)}},edit:({form_id:form_id=[],meta_filters:meta_filters=[],updateFilter:updateFilter=()=>{}})=>{return Fragment([ItemPicker({id:"select-form",noneSelected:"Any form",fetchOptions:async search=>{let forms=await Groundhogg.stores.forms.fetchItems({search:search});return forms.map(item=>({id:item.ID,text:item.name}))},selected:form_id.map(id=>({id:id,text:Groundhogg.stores.forms.get(id).name})),onChange:items=>{updateFilter({form_id:items.map(item=>item.id)})}}),`<label>${__("Filter by fields","groundhogg")}</label>`,SubmissionMetaFilters(meta_filters,updateFilter)])}},{form_id:[],meta_filters:[]}));const StepPicker=(type,step_id,updateFilter)=>ItemPicker({id:"select-webhook",noneSelected:"Any webhook",fetchOptions:async search=>{let steps=await Groundhogg.stores.steps.fetchItems({search:search,step_type:type,status:"active"});return steps.map(item=>({id:item.ID,text:item.data.step_title}))},selected:step_id.map(id=>({id:id,text:Groundhogg.stores.steps.get(id).data.step_title})),onChange:items=>{updateFilter({step_id:items.map(item=>item.id)})}});if(typeof Groundhogg.rawStepTypes.http_post!=="undefined"){ContactFilterRegistry.registerFilter(createPastDateFilter("webhook_response","Webhook Response","submissions",{display:({step_id:step_id=[]})=>{if(!step_id.length){return"Any webhook response"}return`Webhook response from ${orList(step_id.map(id=>bold(Groundhogg.stores.steps.get(id).data.step_title)))}`},preload:({step_id:step_id=[]})=>{if(step_id.length){return Groundhogg.stores.steps.maybeFetchItems(step_id)}},edit:({step_id:step_id=[],meta_filters:meta_filters=[],updateFilter:updateFilter=()=>{}})=>{return Fragment([StepPicker("http_post",step_id,updateFilter),`<label>${__("Filter by fields","groundhogg")}</label>`,SubmissionMetaFilters(meta_filters,updateFilter)])}},{step_id:[],meta_filters:[]}))}if(typeof Groundhogg.rawStepTypes.webhook_listener!=="undefined"){ContactFilterRegistry.registerFilter(createPastDateFilter("webhook_request","Webhook Request","submissions",{display:({step_id:step_id=[]})=>{if(!step_id.length){return"Any webhook request"}return`Webhook request to ${orList(step_id.map(id=>bold(Groundhogg.stores.steps.get(id).data.step_title)))}`},preload:({step_id:step_id=[]})=>{if(step_id.length){return Groundhogg.stores.steps.maybeFetchItems(step_id)}},edit:({step_id:step_id=[],meta_filters:meta_filters=[],updateFilter:updateFilter=()=>{}})=>{return Fragment([StepPicker("webhook_listener",step_id,updateFilter),`<label>${__("Filter by fields","groundhogg")}</label>`,SubmissionMetaFilters(meta_filters,updateFilter)])}},{step_id:[],meta_filters:[]}))}if(!Groundhogg.filters){Groundhogg.filters={}}Groundhogg.filters.ContactFilters=ContactFilters;Groundhogg.filters.ContactFilterDisplay=ContactFilterDisplay;Groundhogg.filters.ContactFilterRegistry=ContactFilterRegistry;Groundhogg.filters.functions={createFilters:createFilters,registerFilter:registerFilter,registerFilterGroup:registerFilterGroup,ComparisonsTitleGenerators:ComparisonsTitleGenerators,AllComparisons:AllComparisons,NumericComparisons:NumericComparisons,StringComparisons:StringComparisons,standardActivityDateOptions:standardActivityDateOptions,standardActivityDateTitle:standardActivityDateTitle,standardActivityDateDefaults:standardActivityDateDefaults,standardActivityDateFilterOnMount:standardActivityDateFilterOnMount,BasicTextFilter:BasicTextFilter,registerActivityFilter:registerActivityFilter,registerActivityFilterWithValue:registerActivityFilterWithValue}})(jQuery);
     65          `,filterCount(filter),standardActivityDateOptions(filter)].join("")},onMount(filter,updateFilter){onMount(filter,updateFilter);$("#filter-value,#filter-value-compare").on("change",e=>{updateFilter({[e.target.name]:e.target.value})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...defaults,...standardActivityDateDefaults,...filterCountDefaults,value:0,value_compare:"greater_than_or_equal_to"},...rest})};registerActivityFilterWithValue("custom_activity","activity",__("Custom Activity","groundhogg"),{view:({activity})=>`<b>${activity}</b>`,edit:({activity,...filter})=>{return[input({id:"filter-activity-type",name:"activity",value:activity,placeholder:"custom_activity"}),`<label>${__("Filter by activity meta","groundhogg")}</label>`,`<div id="custom-activity-meta-filters"></div>`].join("")},onMount(filter,updateFilter){$("#filter-activity-type").on("input",e=>{updateFilter({activity:e.target.value})});let{meta_filters=[]}=filter;inputRepeater("#custom-activity-meta-filters",{rows:meta_filters,cells:[props=>input({placeholder:"Key",className:"input",...props}),({value,...props})=>select({selected:value,options:AllComparisons,...props}),props=>input({placeholder:"Value",className:"input",...props})],addRow:()=>["","equals",""],onChange:rows=>{updateFilter({meta_filters:rows})}}).mount()},defaults:{activity:"",meta_filters:[]}});registerFilterGroup("query","Query");registerFilter("saved_search","query",__("Saved Search"),{view:({compare="in",search})=>{return sprintf(__("Is %s search %s"),compare==="in"?"in":"not in",bold(SearchesStore.get(search)?.name))},edit:({compare})=>{return[select({name:"filter_compare",id:"filter-compare",options:{in:__("In"),not_in:__("Not in")},selected:compare}),select({name:"filter_search",id:"filter-search"})].join("")},onMount:({search},updateFilter)=>{SearchesStore.maybeFetchItems().then(items=>{$("#filter-search").select2({data:[{id:"",text:""},...items.map(({id,name})=>({id:id,text:name,selected:id===search}))],placeholder:__("Type to search...")}).on("change",e=>{updateFilter({search:e.target.value})})});$("#filter-compare").on("change",e=>{updateFilter({compare:e.target.value})})},defaults:{compare:"in",search:null},preload:({search})=>{if(!SearchesStore.hasItems()){return SearchesStore.fetchItems([])}}});ContactFilterRegistry.registerFilter(createFilter("sub_query","Sub Query","query",{display:({include_filters=[],exclude_filters=[]})=>{let texts=[ContactFilterRegistry.displayFilters(include_filters),ContactFilterRegistry.displayFilters(exclude_filters)];if(include_filters.length&&exclude_filters.length){return texts.join(' <abbr title="exclude">and exclude</abbr> ')}if(exclude_filters.length){return sprintf('<abbr title="exclude">Exclude</abbr> %s',texts[1])}if(include_filters.length){return texts[0]}throw new Error("No filters defined.")},edit:({include_filters=[],exclude_filters=[],updateFilter})=>{return Fragment([Div({className:"include-search-filters"},[Filters({id:"sub-query-filters",filters:include_filters,filterRegistry:ContactFilterRegistry,onChange:include_filters=>updateFilter({include_filters:include_filters})})]),Div({className:"exclude-search-filters"},[Filters({id:"sub-query-exclude-filters",filters:exclude_filters,filterRegistry:ContactFilterRegistry,onChange:exclude_filters=>updateFilter({exclude_filters:exclude_filters})})])])},preload:({include_filters=[],exclude_filters=[]})=>{return Promise.all([ContactFilterRegistry.preloadFilters(include_filters),ContactFilterRegistry.preloadFilters(exclude_filters)])}},{}));ContactFilterRegistry.registerFilter(createFilter("secondary_related","Is Child Of","query",{edit:({object_type="",object_id="",updateFilter})=>Fragment([Input({id:"object-type",name:"object_type",value:object_type,placeholder:"Parent Type",onInput:e=>{updateFilter({object_type:e.target.value})}}),Input({type:"number",id:"object-id",name:"object_id",value:object_id,placeholder:"Parent ID",min:0,onInput:e=>{updateFilter({object_id:e.target.value})}})]),display:({object_type,object_id})=>{if(!object_type){throw new Error("Type be defined")}if(!object_id){return`Is a child of ${object_type}`}return`Is a child of ${object_type} with ID ${object_id}`}},{object_type:"contact"}));ContactFilterRegistry.registerFilter(createFilter("primary_related","Is Parent Of","query",{edit:({object_type="",object_id="",updateFilter})=>Fragment([Input({id:"object-type",name:"object_type",value:object_type,placeholder:"Child Type",onInput:e=>{updateFilter({object_type:e.target.value})}}),Input({type:"number",id:"object-id",name:"object_id",value:object_id,placeholder:"Child ID",min:0,onInput:e=>{updateFilter({object_id:e.target.value})}})]),display:({object_type,object_id})=>{if(!object_type){throw new Error("Type must be defined")}if(!object_id){return`Is a parent of ${object_type}`}return`Is a parent of ${object_type} with ID ${object_id}`}},{object_type:"contact"}));registerFilterGroup("date","Date");const CurrentDateCompareFilterFactory=(id,name,type,formatter)=>createFilter(id,name,"date",{edit:({compare="",after="",before="",updateFilter})=>Fragment([Select({id:"select-compare",selected:compare,options:{after:"After",before:"Before",between:"Between"},onChange:e=>{updateFilter({compare:e.target.value})}}),compare==="before"?null:Input({type:type,id:"after-date",name:"after_date",value:after,placeholder:"After...",onChange:e=>{updateFilter({after:e.target.value})}}),compare==="after"?null:Input({type:type,id:"before-date",name:"before_date",value:before,placeholder:"Before...",min:0,onInput:e=>{updateFilter({before:e.target.value})}})]),display:({compare="",after,before})=>{let prefix=`<b>${name}</b>`;switch(compare){case"between":return ComparisonsTitleGenerators.between(prefix,formatter(after),formatter(before));case"after":return ComparisonsTitleGenerators.after(prefix,formatter(after));case"before":return ComparisonsTitleGenerators.before(prefix,formatter(before));default:throw new Error("Invalid date comparison.")}}},{compare:"between",before:"",after:""});ContactFilterRegistry.registerFilter(CurrentDateCompareFilterFactory("current_datetime","Current Date & Time","datetime-local",formatDateTime));ContactFilterRegistry.registerFilter(CurrentDateCompareFilterFactory("current_date","Current Date","date",formatDate));ContactFilterRegistry.registerFilter(CurrentDateCompareFilterFactory("current_time","Current Time","time",time=>formatTime(`2000-01-01T${time}`)));const dayList={0:__("Sunday"),1:__("Monday"),2:__("Tuesday"),3:__("Wednesday"),4:__("Thursday"),5:__("Friday"),6:__("Saturday")};ContactFilterRegistry.registerFilter(createFilter("day_of_week","Day of Week","date",{edit:({days=[],updateFilter})=>{return ItemPicker({id:"days-of-week-picker",noneSelected:"Select a day",fetchOptions:async search=>assoc2array(dayList).filter(option=>option.text.match(new RegExp(search,"i"))),selected:days.map(day=>({id:day,text:dayList[day]})),onChange:items=>{updateFilter({days:items.map(item=>item.id)})}})},display:({days=[]})=>sprintf(__("Today is a %s"),orList(days.map(day=>bold(dayList[day]))))}));const dateList={1:__("1st"),2:__("2nd"),3:__("3rd"),4:__("4th"),5:__("5th"),6:__("6th"),7:__("7th"),8:__("8th"),9:__("9th"),10:__("10th"),11:__("11th"),12:__("12th"),13:__("13th"),14:__("14th"),15:__("15th"),16:__("16th"),17:__("17th"),18:__("18th"),19:__("19th"),20:__("20th"),21:__("21st"),22:__("22nd"),23:__("23rd"),24:__("24th"),25:__("25th"),26:__("26th"),27:__("27th"),28:__("28th"),29:__("29th"),30:__("30th"),31:__("31st"),0:__("Last")};ContactFilterRegistry.registerFilter(createFilter("day_of_month","Day of Month","date",{edit:({dates=[],updateFilter})=>{return ItemPicker({id:"days-of-week-picker",noneSelected:"Select a day",fetchOptions:async search=>assoc2array(dateList).filter(option=>option.text.match(new RegExp(search,"i"))),selected:dates.map(date=>({id:date,text:dateList[date]})),onChange:items=>{updateFilter({dates:items.map(item=>item.id)})}})},display:({dates=[]})=>sprintf(__("Today is the %s of the month"),orList(dates.map(date=>bold(dateList[date]))))}));registerFilterGroup("submissions","Submissions");const SubmissionMetaFilters=(meta_filters,updateFilter)=>InputRepeater({id:"submission-meta-filters",rows:meta_filters,cells:[props=>Input({...props,placeholder:"Field Name"}),({value,...props})=>Select({selected:value,options:AllComparisons,...props}),props=>Input({...props,placeholder:"Value"})],fillRow:()=>["","equals",""],onChange:rows=>{updateFilter({meta_filters:rows})}});ContactFilterRegistry.registerFilter(createPastDateFilter("form_submissions","Form Submissions","submissions",{display:({form_id=[]})=>{if(!form_id.length){return"Submitted any form"}return`Submitted ${orList(form_id.map(id=>bold(Groundhogg.stores.forms.get(id).name)))}`},preload:({form_id=[]})=>{if(form_id.length){return Groundhogg.stores.forms.maybeFetchItems(form_id)}},edit:({form_id=[],meta_filters=[],updateFilter=()=>{}})=>{return Fragment([ItemPicker({id:"select-form",noneSelected:"Any form",fetchOptions:async search=>{let forms=await Groundhogg.stores.forms.fetchItems({search:search});return forms.map(item=>({id:item.ID,text:item.name}))},selected:form_id.map(id=>({id:id,text:Groundhogg.stores.forms.get(id).name})),onChange:items=>{updateFilter({form_id:items.map(item=>item.id)})}}),`<label>${__("Filter by fields","groundhogg")}</label>`,SubmissionMetaFilters(meta_filters,updateFilter)])}},{form_id:[],meta_filters:[]}));const StepPicker=(type,step_id,updateFilter)=>ItemPicker({id:"select-webhook",noneSelected:"Any webhook",fetchOptions:async search=>{let steps=await Groundhogg.stores.steps.fetchItems({search:search,step_type:type,status:"active"});return steps.map(item=>({id:item.ID,text:item.data.step_title}))},selected:step_id.map(id=>({id:id,text:Groundhogg.stores.steps.get(id).data.step_title})),onChange:items=>{updateFilter({step_id:items.map(item=>item.id)})}});if(typeof Groundhogg.rawStepTypes.http_post!=="undefined"){ContactFilterRegistry.registerFilter(createPastDateFilter("webhook_response","Webhook Response","submissions",{display:({step_id=[]})=>{if(!step_id.length){return"Any webhook response"}return`Webhook response from ${orList(step_id.map(id=>bold(Groundhogg.stores.steps.get(id).data.step_title)))}`},preload:({step_id=[]})=>{if(step_id.length){return Groundhogg.stores.steps.maybeFetchItems(step_id)}},edit:({step_id=[],meta_filters=[],updateFilter=()=>{}})=>{return Fragment([StepPicker("http_post",step_id,updateFilter),`<label>${__("Filter by fields","groundhogg")}</label>`,SubmissionMetaFilters(meta_filters,updateFilter)])}},{step_id:[],meta_filters:[]}))}ContactFilterRegistry.registerFilter(createPastDateFilter("wp_fusion_activity","WP Fusion","activity",{display:({event_name="",event_name_compare,event_value="",event_value_compare})=>{if(!event_name){return"Any WP Fusion activity"}let text=sprintf(`WP Fusion Event: %s`,ComparisonsTitleGenerators[event_name_compare](bold("Name"),`<code>${event_name}</code>`));if(event_value){text+=", "+ComparisonsTitleGenerators[event_value_compare](bold("Value"),`<code>${event_value}</code>`)}return text},edit:({event_name="",event_value="",event_value_compare="equals",event_name_compare="equals",updateFilter=()=>{}})=>{return Fragment([MakeEl.Label({for:"event-name"},"Event Name"),MakeEl.InputGroup([Select({id:"event-name-compare",name:"event_name_compare",selected:event_name_compare,options:StringComparisons,onChange:e=>{updateFilter({event_name_compare:e.target.value})}}),Input({id:"event-name",name:"event_name",value:event_name,placeholder:"Event Name",onChange:e=>{updateFilter({event_name:e.target.value})}})]),MakeEl.Label({for:"event-value"},"Event Value"),MakeEl.InputGroup([Select({id:"event-value-compare",selected:event_value_compare,options:AllComparisons,onChange:e=>{updateFilter({event_value_compare:e.target.value})}}),Input({id:"event-value",value:event_value,placeholder:"Event value",onChange:e=>{updateFilter({event_value:e.target.value})}})])])}},{event_name_compare:"equals",event_name:"",event_value_compare:"equals",event_value:""}));if(typeof Groundhogg.rawStepTypes.webhook_listener!=="undefined"){ContactFilterRegistry.registerFilter(createPastDateFilter("webhook_request","Webhook Request","submissions",{display:({step_id=[]})=>{if(!step_id.length){return"Any webhook request"}return`Webhook request to ${orList(step_id.map(id=>bold(Groundhogg.stores.steps.get(id).data.step_title)))}`},preload:({step_id=[]})=>{if(step_id.length){return Groundhogg.stores.steps.maybeFetchItems(step_id)}},edit:({step_id=[],meta_filters=[],updateFilter=()=>{}})=>{return Fragment([StepPicker("webhook_listener",step_id,updateFilter),`<label>${__("Filter by fields","groundhogg")}</label>`,SubmissionMetaFilters(meta_filters,updateFilter)])}},{step_id:[],meta_filters:[]}))}if(!Groundhogg.filters){Groundhogg.filters={}}Groundhogg.filters.ContactFilters=ContactFilters;Groundhogg.filters.ContactFilterDisplay=ContactFilterDisplay;Groundhogg.filters.ContactFilterRegistry=ContactFilterRegistry;Groundhogg.filters.functions={createFilters:createFilters,registerFilter:registerFilter,registerFilterGroup:registerFilterGroup,ComparisonsTitleGenerators:ComparisonsTitleGenerators,AllComparisons:AllComparisons,NumericComparisons:NumericComparisons,StringComparisons:StringComparisons,standardActivityDateOptions:standardActivityDateOptions,standardActivityDateTitle:standardActivityDateTitle,standardActivityDateDefaults:standardActivityDateDefaults,standardActivityDateFilterOnMount:standardActivityDateFilterOnMount,BasicTextFilter:BasicTextFilter,registerActivityFilter:registerActivityFilter,registerActivityFilterWithValue:registerActivityFilterWithValue}})(jQuery);
  • groundhogg/tags/4.2.9/db/query/filters.php

    r3343709 r3400645  
    614614                $where->notContains( $column, $value );
    615615                break;
     616            case '^':
    616617            case 'starts_with':
    617618            case 'begins_with':
     
    621622                $where->notLike( $column, $where->esc_like( $value ) . '%' );
    622623                break;
     624            case '$':
    623625            case 'ends_with':
    624626                $where->endsWith( $column, $value );
  • groundhogg/tags/4.2.9/db/query/where.php

    r3343709 r3400645  
    269269    public function compare( $column, $value, $compare = '=', $format = false ) {
    270270
     271        // handle other comparisons by mapping to other functions
     272        switch ( strtolower( $compare ) ) {
     273            case 'contains':
     274                return $this->contains( $column, $value );
     275            case 'not_contains':
     276                return $this->notContains( $column, $value );
     277            case '^':
     278            case 'starts_with':
     279            case 'begins_with':
     280                return $this->startsWith( $column, $value );
     281            case '$':
     282            case 'ends_with':
     283                return $this->endsWith( $column, $value );
     284            case 'does_not_start_with':
     285                return $this->notLike( $column, $this->esc_like( $value ) . '%' );
     286            case 'does_not_end_with':
     287                return $this->notLike( $column, '%' . $this->esc_like( $value ) );
     288            case 'empty':
     289                return $this->empty( $column );
     290            case 'not_empty':
     291                return $this->notEmpty( $column );
     292        }
     293
    271294        $column  = $this->sanitize_column( $column );
    272295        $compare = $this->symbolize_comparison( $compare );
  • groundhogg/tags/4.2.9/groundhogg.php

    r3395861 r3400645  
    44 * Plugin URI: https://www.groundhogg.io/?utm_source=wp-plugins&utm_campaign=plugin-uri&utm_medium=wp-dash
    55 * Description: CRM and marketing automation for WordPress
    6  * Version: 4.2.8
     6 * Version: 4.2.9
    77 * Author: Groundhogg Inc.
    88 * Author URI: https://www.groundhogg.io/?utm_source=wp-plugins&utm_campaign=author-uri&utm_medium=wp-dash
     
    2525if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
    2626
    27 define( 'GROUNDHOGG_VERSION', '4.2.8' );
    28 define( 'GROUNDHOGG_PREVIOUS_STABLE_VERSION', '4.2.7' );
     27define( 'GROUNDHOGG_VERSION', '4.2.9' );
     28define( 'GROUNDHOGG_PREVIOUS_STABLE_VERSION', '4.2.8' );
    2929
    3030define( 'GROUNDHOGG__FILE__', __FILE__ );
  • groundhogg/tags/4.2.9/includes/contact-query.php

    r3343709 r3400645  
    11541154
    11551155            $alias = $activityQuery->joinMeta( $key );
    1156             $activityQuery->where()->compare( "$alias.meta_value", $value, $compare );
     1156
     1157            Filters::string( "$alias.meta_value", [
     1158                'compare' => $compare,
     1159                'value'   => $value
     1160            ], $activityQuery->where() );
     1161        }
     1162    }
     1163
     1164    /**
     1165     * Special handler for WPFusion activity
     1166     *
     1167     * @throws \Exception
     1168     *
     1169     * @param  Where  $where
     1170     * @param $filter
     1171     *
     1172     * @return void
     1173     */
     1174    public static function filter_wp_fusion_activity( $filter, Where $where ) {
     1175
     1176        $filter = wp_parse_args( $filter, [
     1177            'event_name'          => '',
     1178            'event_name_compare'  => 'equals',
     1179            'event_value'         => '',
     1180            'event_value_compare' => 'equals'
     1181        ] );
     1182
     1183        $activityQuery = self::basic_activity_filter( 'wp_fusion', $filter, $where );
     1184
     1185        if ( ! empty( $filter['event_name'] ) ){
     1186            $alias = $activityQuery->joinMeta( 'event_name' );
     1187
     1188            Filters::string( "$alias.meta_value", [
     1189                'compare' => $filter['event_name_compare'],
     1190                'value'   => $filter['event_name']
     1191            ], $activityQuery->where() );
     1192        }
     1193
     1194        if ( ! empty( $filter['event_value'] ) ) {
     1195            $alias = $activityQuery->joinMeta( 'event_value' );
     1196
     1197            Filters::string( "$alias.meta_value", [
     1198                'compare' => $filter['event_value_compare'],
     1199                'value'   => $filter['event_value']
     1200            ], $activityQuery->where() );
    11571201        }
    11581202    }
     
    11961240
    11971241            $alias = $submissionQuery->joinMeta( $key );
    1198             $submissionQuery->where()->compare( "$alias.meta_value", $value, $compare );
     1242
     1243            Filters::string( "$alias.meta_value", [
     1244                'compare' => $compare,
     1245                'value'   => $value
     1246            ], $submissionQuery->where() );
     1247
    11991248        }
    12001249
     
    15381587
    15391588        self::filter_current_datetime( $filter, $where );
     1589    }
     1590
     1591    /**
     1592     * If today's date is a specific day of the week
     1593     *
     1594     * @param $filter
     1595     * @param  Where  $where
     1596     *
     1597     * @return void
     1598     */
     1599    public static function filter_day_of_week( $filter, Where $where ) {
     1600
     1601        $days = wp_parse_id_list( $filter['days'] );
     1602        $today = new DateTimeHelper();
     1603
     1604        if ( in_array( absint( $today->format( 'w') ), $days ) ){
     1605            $where->addCondition( '1=1' ); // always true
     1606        } else {
     1607            $where->addCondition( '0=1' ); // short circuit false
     1608        }
     1609    }
     1610
     1611    /**
     1612     * If today's date is a specific day of the month
     1613     *
     1614     * @param $filter
     1615     * @param  Where  $where
     1616     *
     1617     * @return void
     1618     */
     1619    public static function filter_day_of_month( $filter, Where $where ) {
     1620
     1621        $dates = wp_parse_id_list( $filter['dates'] );
     1622        $today = new DateTimeHelper();
     1623
     1624        // using last
     1625        if ( in_array( 0, $dates ) && $today->format( 'j' ) === $today->format('t') ){
     1626            $where->addCondition( '1=1' ); // always true
     1627            return;
     1628        }
     1629
     1630        if ( in_array( absint( $today->format( 'j') ), $dates ) ){
     1631            $where->addCondition( '1=1' ); // always true
     1632        } else {
     1633            $where->addCondition( '0=1' ); // short circuit false
     1634        }
    15401635    }
    15411636
  • groundhogg/tags/4.2.9/includes/form/form-v2.php

    r3395861 r3400645  
    19291929        if ( isset_not_empty( $recaptcha, 'enabled' ) && is_recaptcha_enabled() ) {
    19301930            $html .= $this->render_field( $recaptcha );
     1931            wp_enqueue_script( 'groundhogg-google-recaptcha' );
    19311932        }
    19321933
    19331934        if ( isset_not_empty( $turnstile, 'enabled' ) && is_turnstile_enabled() ) {
    19341935            $html .= $this->render_field( $turnstile );
     1936            wp_enqueue_script( 'cf-turnstile' );
    19351937        }
    19361938
  • groundhogg/tags/4.2.9/includes/scripts.php

    r3395861 r3400645  
    126126            ] );
    127127
    128             $form_v2_dependencies[] = 'google-recaptcha';
     128//          $form_v2_dependencies[] = 'google-recaptcha';
    129129            $form_dependencies[]    = 'groundhogg-google-recaptcha';
    130130        }
     
    132132        if ( is_turnstile_enabled() ){
    133133            wp_register_script( 'cf-turnstile', 'https://challenges.cloudflare.com/turnstile/v0/api.js' );
    134             $form_v2_dependencies[] = 'cf-turnstile';
     134//          $form_v2_dependencies[] = 'cf-turnstile';
    135135        }
    136136
  • groundhogg/trunk/README.txt

    r3395861 r3400645  
    77Tested up to: 6.8
    88Requires PHP: 7.1
    9 Stable tag: 4.2.8
     9Stable tag: 4.2.9
    1010License: GPLv3
    1111License URI: https://www.gnu.org/licenses/gpl.md
     
    378378
    379379== Changelog ==
     380
     381= 4.2.9 (2025-11-21) =
     382* ADDED WP Fusion event tracking filter so you don't **have** to use the custom activity filter.
     383* ADDED "Day of Week" and "Day of Month" filters for conditional logic.
     384* ADDED Email preview action to the broadcasts table and broadcast report.
     385* IMPROVED Recaptcha and Turnstile scripts are now only enqueued if the fields are actually being used.
     386* FIXED Some of the meta-comparisons for the custom activity filter and submission filters not returning correct results.
    380387
    381388= 4.2.8 (2025-11-14) =
  • groundhogg/trunk/admin/broadcasts/broadcasts-table.php

    r3394550 r3400645  
    244244        ], $broadcast->is_email() ? esc_html__( 'Edit email', 'groundhogg' ) : esc_html__( 'Edit SMS' , 'groundhogg' ) );
    245245
     246        if ( $broadcast->is_email() ){
     247            $actions[] = html()->a( '#', esc_html__( 'Preview', 'groundhogg' ), [ 'class' => 'gh-email-preview', 'data-id' => $broadcast->get_object_id() ] );
     248        }
     249
    246250        // Add query action
    247251        $query = $broadcast->get_query();
  • groundhogg/trunk/admin/emails/emails-table.php

    r3394550 r3400645  
    330330        switch ( $this->get_view() ) {
    331331            default:
     332                $actions[] = [ 'class' => 'edit', 'display' => esc_html__( 'Edit' , 'groundhogg' ), 'url' => $item->admin_link() ];
    332333                $actions[] = [ 'class' => 'gh-email-preview', 'display' => esc_html__( 'Preview' , 'groundhogg' ), 'url' => '#' ];
    333                 $actions[] = [ 'class' => 'edit', 'display' => esc_html__( 'Edit' , 'groundhogg' ), 'url' => $item->admin_link() ];
    334334                $actions[] = [
    335335                    'class'   => 'duplicate',
  • groundhogg/trunk/admin/reports/reports-page.php

    r3394550 r3400645  
    141141                wp_enqueue_style( 'baremetrics-calendar' );
    142142                wp_enqueue_script( 'groundhogg-admin-reporting' );
     143                wp_enqueue_script( 'groundhogg-admin-components' );
    143144
    144145                $start = get_request_var( 'start' );
  • groundhogg/trunk/admin/reports/views/broadcast-single.php

    r3343709 r3400645  
    1616<div class="display-flex gap-20 align-center">
    1717    <h1 class="report-title"><?php echo esc_html( $broadcast->get_title() ) ?></h1>
     18    <?php if ( $broadcast->is_email() ): ?>
     19        <a href="#" class="gh-button secondary gh-email-preview" data-id="<?php echo esc_attr( $broadcast->get_object_id() ); ?>"><?php esc_html_e( 'Preview', 'groundhogg' ); ?></a>
     20    <?php endif; ?>
    1821</div>
    1922<div class="display-grid gap-20">
  • groundhogg/trunk/assets/js/admin/components.js

    r3314835 r3400645  
    17881788
    17891789  $(() => {
    1790     $(document).on('click', 'table.wp-list-table .gh-email-preview', e => {
     1790    $(document).on('click', 'a.gh-email-preview', e => {
    17911791      e.preventDefault()
    17921792
    1793       EmailPreviewModal(parseInt($(e.currentTarget).closest('tr').attr('id')), {})
     1793      let emailId = e.currentTarget.dataset.id ?? e.currentTarget.closest('tr').id
     1794
     1795      EmailPreviewModal(parseInt(emailId), {})
    17941796    })
    17951797  })
  • groundhogg/trunk/assets/js/admin/components.min.js

    r3314835 r3400645  
    1 ($=>{const{modal,errorDialog,loadingDots,select,uuid,addMediaToBasicTinyMCE,specialChars,tinymceElement,searchOptionsWidget,input,isNumeric,icons,dialog,tooltip,regexp,isValidEmail,loadingModal,textarea,spinner,skeleton,adminPageURL}=Groundhogg.element;const{Div,H2,H4,Toggle,Img,An,Span,ModalFrame,Iframe,makeEl,Button,Modal,ModalWithHeader,Dashicon,ToolTip,Input,TinyMCE,Label,Fragment,ItemPicker,Skeleton,Pg,Form,Textarea,InputGroup}=MakeEl;const{contacts:ContactsStore,tags:TagsStore,forms:FormsStore,emails:EmailsStore}=Groundhogg.stores;const{post,routes,postFormData}=Groundhogg.api;const{tagPicker}=Groundhogg.pickers;const{userHasCap,getOwner}=Groundhogg.user;const{sprintf,__,_x,_n}=wp.i18n;const{formatDateTime}=Groundhogg.formatting;const{currentUser}=Groundhogg;const{maybeCall,debounce,jsonCopy}=Groundhogg.functions;const selectContactModal=({onSelect:onSelect=()=>{},onClose:onClose=()=>{},exclude:exclude=[]})=>{Modal({dialogClasses:"no-padding",width:"400px",onOpen:e=>{document.getElementById("quick-search-input").focus()}},({close})=>QuickSearch({itemProps:contact=>({onClick:e=>{onSelect(contact);close()}}),queryOverrides:{limit:15,exclude:exclude}}))};const betterTagPicker=(el,{selected:selected=[],removeTags:removeTags=[],addTags:addTags=[],onChange:onChange=changes=>{}})=>{const $el=$(el);let timeout;const template=()=>{return`
     1($=>{const{modal,errorDialog,loadingDots,select,uuid,addMediaToBasicTinyMCE,specialChars,tinymceElement,searchOptionsWidget,input,isNumeric,icons,dialog,tooltip,regexp,isValidEmail,loadingModal,textarea,spinner,skeleton,adminPageURL}=Groundhogg.element;const{Div,H2,H4,Toggle,Img,An,Span,ModalFrame,Iframe,makeEl,Button,Modal,ModalWithHeader,Dashicon,ToolTip,Input,TinyMCE,Label,Fragment,ItemPicker,Skeleton,Pg,Form,Textarea,InputGroup}=MakeEl;const{contacts:ContactsStore,tags:TagsStore,forms:FormsStore,emails:EmailsStore}=Groundhogg.stores;const{post,routes,postFormData}=Groundhogg.api;const{tagPicker}=Groundhogg.pickers;const{userHasCap,getOwner}=Groundhogg.user;const{sprintf,__,_x,_n}=wp.i18n;const{formatDateTime}=Groundhogg.formatting;const{currentUser}=Groundhogg;const{maybeCall,debounce,jsonCopy}=Groundhogg.functions;const selectContactModal=({onSelect=()=>{},onClose=()=>{},exclude=[]})=>{Modal({dialogClasses:"no-padding",width:"400px",onOpen:e=>{document.getElementById("quick-search-input").focus()}},({close})=>QuickSearch({itemProps:contact=>({onClick:e=>{onSelect(contact);close()}}),queryOverrides:{limit:15,exclude:exclude}}))};const betterTagPicker=(el,{selected=[],removeTags=[],addTags=[],onChange=changes=>{}})=>{const $el=$(el);let timeout;const template=()=>{return`
    22          <div class="gh-tags">
    33              ${selected.map(tag=>`<span class="gh-tag${removeTags.includes(tag.ID)?" remove":""}">${tag.data.tag_name} <span data-id="${tag.ID}" class="remove-tag dashicons dashicons-no-alt"></span></span>`).join("")}
     
    66                  <span class="dashicons dashicons-plus-alt2"></span>
    77              </button>
    8           </div>`};const mount=()=>{$el.html(template());onMount()};const informChanges=()=>{onChange({removeTags:removeTags,addTags:addTags})};const onMount=()=>{tooltip($el.find(".add-tag"),{content:__("Add a tag","groundhogg")});$el.find(".gh-tag .remove-tag").on("click",e=>{let tagId=parseInt(e.currentTarget.dataset.id);if(removeTags.includes(tagId)){removeTags.splice(removeTags.indexOf(tagId),1)}else{removeTags.push(tagId)}informChanges();mount()});$el.find(".gh-tag .remove-adding-tag").on("click",e=>{let tagId=parseInt(e.currentTarget.dataset.id);if(addTags.includes(tagId)){addTags.splice(addTags.indexOf(tagId),1)}informChanges();mount()});$el.find(".add-tag").on("click",e=>{const filterTags=tags=>tags.filter(t=>!selected.map(_t=>_t.ID).includes(t.ID)&&!addTags.includes(t.ID)).sort((a,b)=>b.ID-a.ID);let initialOptions=filterTags(TagsStore.getItems());searchOptionsWidget({target:e.currentTarget,position:"fixed",noOptions:__("No tags found...","groundhogg"),options:initialOptions,filterOption:({data},search)=>data.tag_name.match(regexp(search)),filterOptions:(opts,search)=>{if(!search){return opts}if(userHasCap("add_tags")){opts.unshift({ID:search,data:{tag_name:sprintf(__('Add "%s"',"groundhogg"),search)}})}return opts},renderOption:({data})=>data.tag_name,onClose:()=>{mount()},onInput:(search,widget)=>{if(timeout){clearTimeout(timeout)}timeout=setTimeout(()=>{TagsStore.fetchItems({search:search}).then(()=>{widget.options=filterTags(TagsStore.getItems());widget.mountOptions()})},1500)},onSelect:tag=>{let{ID}=tag;if(!isNumeric(ID)){TagsStore.post({data:{tag_name:ID}}).then(t=>{addTags.push(t.ID);informChanges();mount()});return}addTags.push(ID);informChanges()},onOpen:widget=>{if(!initialOptions.length){TagsStore.fetchItems().then(()=>{widget.options=filterTags(TagsStore.getItems());widget.mountOptions()})}}}).mount()})};TagsStore.itemsFetched(selected);mount()};const quickEditContactModal=({contact,prefix:prefix="quick-edit",onEdit:onEdit=contact=>{},additionalFields:additionalFields=()=>"",additionalFieldsOnMount:additionalFieldsOnMount=()=>{}})=>{if(contact&&contact.tags){TagsStore.itemsFetched(contact.tags)}const getContact=()=>{return ContactsStore.get(contact.ID)};const quickEdit=contact=>{return`
     8          </div>`};const mount=()=>{$el.html(template());onMount()};const informChanges=()=>{onChange({removeTags:removeTags,addTags:addTags})};const onMount=()=>{tooltip($el.find(".add-tag"),{content:__("Add a tag","groundhogg")});$el.find(".gh-tag .remove-tag").on("click",e=>{let tagId=parseInt(e.currentTarget.dataset.id);if(removeTags.includes(tagId)){removeTags.splice(removeTags.indexOf(tagId),1)}else{removeTags.push(tagId)}informChanges();mount()});$el.find(".gh-tag .remove-adding-tag").on("click",e=>{let tagId=parseInt(e.currentTarget.dataset.id);if(addTags.includes(tagId)){addTags.splice(addTags.indexOf(tagId),1)}informChanges();mount()});$el.find(".add-tag").on("click",e=>{const filterTags=tags=>tags.filter(t=>!selected.map(_t=>_t.ID).includes(t.ID)&&!addTags.includes(t.ID)).sort((a,b)=>b.ID-a.ID);let initialOptions=filterTags(TagsStore.getItems());searchOptionsWidget({target:e.currentTarget,position:"fixed",noOptions:__("No tags found...","groundhogg"),options:initialOptions,filterOption:({data},search)=>data.tag_name.match(regexp(search)),filterOptions:(opts,search)=>{if(!search){return opts}if(userHasCap("add_tags")){opts.unshift({ID:search,data:{tag_name:sprintf(__('Add "%s"',"groundhogg"),search)}})}return opts},renderOption:({data})=>data.tag_name,onClose:()=>{mount()},onInput:(search,widget)=>{if(timeout){clearTimeout(timeout)}timeout=setTimeout(()=>{TagsStore.fetchItems({search:search}).then(()=>{widget.options=filterTags(TagsStore.getItems());widget.mountOptions()})},1500)},onSelect:tag=>{let{ID}=tag;if(!isNumeric(ID)){TagsStore.post({data:{tag_name:ID}}).then(t=>{addTags.push(t.ID);informChanges();mount()});return}addTags.push(ID);informChanges()},onOpen:widget=>{if(!initialOptions.length){TagsStore.fetchItems().then(()=>{widget.options=filterTags(TagsStore.getItems());widget.mountOptions()})}}}).mount()})};TagsStore.itemsFetched(selected);mount()};const quickEditContactModal=({contact,prefix="quick-edit",onEdit=contact=>{},additionalFields=()=>"",additionalFieldsOnMount=()=>{}})=>{if(contact&&contact.tags){TagsStore.itemsFetched(contact.tags)}const getContact=()=>{return ContactsStore.get(contact.ID)};const quickEdit=contact=>{return`
    99          <div class="contact-quick-edit" tabindex="0">
    1010              <div class="gh-header space-between">
     
    8080                  <button class="gh-button primary" id="${prefix}-save">${__("Save Changes","groundhogg")}</button>
    8181              </div>
    82           </div>`};const quickEditMounted=({close,setContent})=>{let payload;const clearPayload=()=>{payload={data:{},meta:{},add_tags:[],remove_tags:[]}};clearPayload();const updateContact=data=>{payload={...data,data:{...payload.data,...data.data},meta:{...payload.meta,...data.meta}}};const $quickEdit=$(".contact-quick-edit");$quickEdit.focus();$(`#${prefix}-save`).on("click",e=>{const $btn=$(e.target);$btn.prop("disabled",true);$btn.text(__("Saving","groundhogg"));const{stop}=loadingDots(`#${prefix}-save`);ContactsStore.patch(contact.ID,payload).then(c=>{stop();clearPayload();onEdit(c);setContent(quickEdit(getContact()));quickEditMounted({close:close,setContent:setContent})}).catch(e=>{stop();clearPayload();setContent(quickEdit(getContact()));quickEditMounted({close:close,setContent:setContent});console.log(e);dialog({type:"error",message:e.message})})});$(`.${prefix}-cancel`).on("click",e=>{clearPayload();close()});betterTagPicker(`#${prefix}-tags-here`,{selected:getContact().tags,onChange:({addTags,removeTags})=>{updateContact({add_tags:addTags,remove_tags:removeTags})}});$(`#${prefix}-first-name, #${prefix}-last-name, #${prefix}-email, #${prefix}-optin-status, #${prefix}-owner`).on("change",e=>{updateContact({data:{[e.target.name]:e.target.value}})});$(`#${prefix}-primary-phone, #${prefix}-primary-phone-extension, #${prefix}-mobile-phone`).on("change",e=>{updateContact({meta:{[e.target.name]:e.target.value}})});additionalFieldsOnMount({prefix:prefix,contact:contact,setPayload:updateContact,getPayload:()=>payload})};const{close,setContent}=modal({content:quickEdit(getContact()),onOpen:quickEditMounted})};const quickAddForm=(selector,{prefix:prefix="quick-add",onCreate:onCreate=()=>{},additionalFields:additionalFields=({prefix})=>"",additionalFieldsOnMount:additionalFieldsOnMount=()=>{}})=>{const quickAddForm=()=>{return`
     82          </div>`};const quickEditMounted=({close,setContent})=>{let payload;const clearPayload=()=>{payload={data:{},meta:{},add_tags:[],remove_tags:[]}};clearPayload();const updateContact=data=>{payload={...data,data:{...payload.data,...data.data},meta:{...payload.meta,...data.meta}}};const $quickEdit=$(".contact-quick-edit");$quickEdit.focus();$(`#${prefix}-save`).on("click",e=>{const $btn=$(e.target);$btn.prop("disabled",true);$btn.text(__("Saving","groundhogg"));const{stop}=loadingDots(`#${prefix}-save`);ContactsStore.patch(contact.ID,payload).then(c=>{stop();clearPayload();onEdit(c);setContent(quickEdit(getContact()));quickEditMounted({close:close,setContent:setContent})}).catch(e=>{stop();clearPayload();setContent(quickEdit(getContact()));quickEditMounted({close:close,setContent:setContent});console.log(e);dialog({type:"error",message:e.message})})});$(`.${prefix}-cancel`).on("click",e=>{clearPayload();close()});betterTagPicker(`#${prefix}-tags-here`,{selected:getContact().tags,onChange:({addTags,removeTags})=>{updateContact({add_tags:addTags,remove_tags:removeTags})}});$(`#${prefix}-first-name, #${prefix}-last-name, #${prefix}-email, #${prefix}-optin-status, #${prefix}-owner`).on("change",e=>{updateContact({data:{[e.target.name]:e.target.value}})});$(`#${prefix}-primary-phone, #${prefix}-primary-phone-extension, #${prefix}-mobile-phone`).on("change",e=>{updateContact({meta:{[e.target.name]:e.target.value}})});additionalFieldsOnMount({prefix:prefix,contact:contact,setPayload:updateContact,getPayload:()=>payload})};const{close,setContent}=modal({content:quickEdit(getContact()),onOpen:quickEditMounted})};const quickAddForm=(selector,{prefix="quick-add",onCreate=()=>{},additionalFields=({prefix})=>"",additionalFieldsOnMount=()=>{}})=>{const quickAddForm=()=>{return`
    8383          <div class="gh-rows-and-columns">
    8484              <div class="gh-row">
     
    170170    #${prefix}-terms,
    171171    #${prefix}-data-consent,
    172     #${prefix}-marketing-consent`).on("change",({target})=>{setPayload({meta:{..._payload.meta,[target.name]:target.checked}})});betterTagPicker(`   #${prefix}-tags-here`,{selected:[],onChange:({addTags})=>{setPayload({tags:addTags})}});additionalFieldsOnMount({prefix:prefix,setPayload:setPayload,getPayload:getPayload})};const internalForm=({contact:contact=false,onSubmit:onSubmit=()=>{}})=>{let selectedForm;const ui=()=>{return`
     172    #${prefix}-marketing-consent`).on("change",({target})=>{setPayload({meta:{..._payload.meta,[target.name]:target.checked}})});betterTagPicker(`   #${prefix}-tags-here`,{selected:[],onChange:({addTags})=>{setPayload({tags:addTags})}});additionalFieldsOnMount({prefix:prefix,setPayload:setPayload,getPayload:getPayload})};const internalForm=({contact=false,onSubmit=()=>{}})=>{let selectedForm;const ui=()=>{return`
    173173          <div class="gh-header">
    174174              <div class="display-flex gap-20 full-width">
     
    180180          <div class="form-wrap">
    181181              ${selectedForm?selectedForm.rendered:`<p>${__("Select a form using the dropdown","groundhogg")}</p>`}
    182           </div>`};return modal({width:500,content:ui(),dialogClasses:"internal-form-wrap",onOpen:({setContent,close})=>{const reMount=()=>{setContent(ui());onMount()};const onMount=()=>{$("#cancel").on("click",()=>close());$(`#select-form`).ghPicker({endpoint:FormsStore.route,width:"100%",placeholder:__("Type to select a form...","groundhogg"),data:[{id:"",text:""},...FormsStore.getItems().map(f=>({id:f.ID,text:f.name,selected:selectedForm&&f.ID==selectedForm.ID}))],getParams:q=>({...q,search:q.term,active:true,contact:contact.ID}),getResults:({items})=>{FormsStore.itemsFetched(items);return items.map(f=>({id:f.ID,text:f.name}))}}).on("select2:select",e=>{selectedForm=FormsStore.get(e.params.data.id);reMount()});if(selectedForm){$(".internal-form-wrap form.gh-form").on("submit",e=>{e.preventDefault();const $form=$(e.currentTarget);handleInternalFormSubmit(selectedForm.ID,$form,c=>{close();onSubmit(c)})})}};onMount()}})};const handleInternalFormSubmit=(formId,$form,onSubmit)=>{let $btn=$form.find(".gh-submit");let origTxt=$btn.text();$btn.prop("disabled",true);$btn.text(__("Submitting","groundhogg"));const{stop}=loadingDots($btn);var data=new FormData($form[0]);if($form.is(".gh-form-v2")){postFormData(`${FormsStore.route}/${formId}/admin`,data).then(r=>{$btn.prop("disabled",false);$btn.text(origTxt);if(r.status&&r.status==="success"){dialog({message:__("Form submitted!")});ContactsStore.itemsFetched([r.contact]);onSubmit(r.contact);return}dialog({message:r.additional_errors[0].message,type:"error"})})}else{data.append("action","groundhogg_ajax_form_submit");$.ajax({method:"POST",url:ajaxurl,data:data,processData:false,contentType:false,cache:false,timeout:6e5,enctype:"multipart/form-data",success:r=>{stop();$btn.prop("disabled",false);$btn.text(origTxt);if(!r.success){dialog({message:r.data[0].message,type:"error"})}else{dialog({message:__("Form submitted!")});ContactsStore.itemsFetched([r.data.contact]);onSubmit(r.data.contact)}},error:e=>{dialog({message:__("Something went wrong...","groundhogg"),type:"error"})}})}};const addContactModal=({prefix:prefix="quick-add",onCreate:onCreate=()=>{},additionalFields:additionalFields=()=>"",additionalFieldsOnMount:additionalFieldsOnMount=()=>{}})=>{let method="quick-add";let selectedForm;const form=()=>{const quickAddForm=()=>{return`
     182          </div>`};return modal({width:500,content:ui(),dialogClasses:"internal-form-wrap",onOpen:({setContent,close})=>{const reMount=()=>{setContent(ui());onMount()};const onMount=()=>{$("#cancel").on("click",()=>close());$(`#select-form`).ghPicker({endpoint:FormsStore.route,width:"100%",placeholder:__("Type to select a form...","groundhogg"),data:[{id:"",text:""},...FormsStore.getItems().map(f=>({id:f.ID,text:f.name,selected:selectedForm&&f.ID==selectedForm.ID}))],getParams:q=>({...q,search:q.term,active:true,contact:contact.ID}),getResults:({items})=>{FormsStore.itemsFetched(items);return items.map(f=>({id:f.ID,text:f.name}))}}).on("select2:select",e=>{selectedForm=FormsStore.get(e.params.data.id);reMount()});if(selectedForm){$(".internal-form-wrap form.gh-form").on("submit",e=>{e.preventDefault();const $form=$(e.currentTarget);handleInternalFormSubmit(selectedForm.ID,$form,c=>{close();onSubmit(c)})})}};onMount()}})};const handleInternalFormSubmit=(formId,$form,onSubmit)=>{let $btn=$form.find(".gh-submit");let origTxt=$btn.text();$btn.prop("disabled",true);$btn.text(__("Submitting","groundhogg"));const{stop}=loadingDots($btn);var data=new FormData($form[0]);if($form.is(".gh-form-v2")){postFormData(`${FormsStore.route}/${formId}/admin`,data).then(r=>{$btn.prop("disabled",false);$btn.text(origTxt);if(r.status&&r.status==="success"){dialog({message:__("Form submitted!")});ContactsStore.itemsFetched([r.contact]);onSubmit(r.contact);return}dialog({message:r.additional_errors[0].message,type:"error"})})}else{data.append("action","groundhogg_ajax_form_submit");$.ajax({method:"POST",url:ajaxurl,data:data,processData:false,contentType:false,cache:false,timeout:6e5,enctype:"multipart/form-data",success:r=>{stop();$btn.prop("disabled",false);$btn.text(origTxt);if(!r.success){dialog({message:r.data[0].message,type:"error"})}else{dialog({message:__("Form submitted!")});ContactsStore.itemsFetched([r.data.contact]);onSubmit(r.data.contact)}},error:e=>{dialog({message:__("Something went wrong...","groundhogg"),type:"error"})}})}};const addContactModal=({prefix="quick-add",onCreate=()=>{},additionalFields=()=>"",additionalFieldsOnMount=()=>{}})=>{let method="quick-add";let selectedForm;const form=()=>{const quickAddForm=()=>{return`
    183183            <div id="${prefix}-quick-add-form"></div>`};const useForm=()=>{return`
    184184            <div class="gh-rows-and-columns">
     
    208208              ${method=="form"?useForm():quickAddForm()}
    209209          </div>
    210       `};const onMount=({close,setContent})=>{const reMount=()=>{setContent(form());onMount({close:close,setContent:setContent})};tooltip(".use-quick-add",{content:__("Use quick-add form","groundhogg")});tooltip(".use-form",{content:__("Use internal form","groundhogg")});$(".use-form").on("click",e=>{method="form";reMount()});$(".use-quick-add").on("click",e=>{method="quick-add";reMount()});$(`.${prefix}-cancel`).on("click",close);if(method=="quick-add"){quickAddForm(`#${prefix}-quick-add-form`,{prefix:prefix,additionalFields:additionalFields,additionalFieldsOnMount:additionalFieldsOnMount,onCreate:c=>{close();onCreate(c)}})}else{$(`#${prefix}-select-form`).ghPicker({endpoint:FormsStore.route,width:"100%",placeholder:__("Type to search...","groundhogg"),data:[{id:"",text:""},...FormsStore.getItems().map(f=>({id:f.ID,text:f.name,selected:selectedForm&&f.ID==selectedForm.ID}))],getParams:q=>({...q,search:q.term,active:true}),getResults:({items})=>{FormsStore.itemsFetched(items);return items.map(f=>({id:f.ID,text:f.name}))}}).on("select2:select",e=>{selectedForm=FormsStore.get(e.params.data.id);reMount()});if(selectedForm){$(".quick-add-wrap form.gh-form").on("submit",e=>{e.preventDefault();var $form=$(e.currentTarget);handleInternalFormSubmit(selectedForm.ID,$form,c=>{close();onCreate(c)})})}}};return modal({content:form(),onOpen:onMount})};const EmailModal=(props,onSend=()=>{})=>{const State=Groundhogg.createState({to:[],from_user:currentUser.ID,from_name:currentUser.data.display_name,from_email:currentUser.data.user_email,cc:[],showCC:false,bcc:[],showBCC:false,subject:"",content:"",sending:false,...props});const EmailAddressPicker=({label:label="",key:key=""})=>ItemPicker({id:`composed-${key}`,label:`${label}:`,style:{flexGrow:1},noneSelected:`${label}...`,tags:true,selected:State[key].map(v=>({id:v,text:v})),fetchOptions:search=>ContactsStore.fetchItems({search:search}).then(items=>items.map(item=>({id:item.data.email,text:item.data.email}))),isValidSelection:isValidEmail,onChange:items=>State.set({[key]:items.map(item=>item.id)})});return Modal({className:"send-email",dialogClasses:"gh-panel",overlay:false,onClose:()=>{wp.editor.remove("composed-content")}},({close,morph:realMorph})=>{const morph=()=>realMorph({});return Form({id:"compose-email-form",className:"display-flex column gap-10",onSubmit:e=>{e.preventDefault();const{to,from_email,from_name,cc,bcc,subject,content}=State;if(!content){errorDialog({message:"Please add a message."});return false}if(!to.length){errorDialog({message:"Please add a least one recipient."});return false}State.set({sending:true});morph();post(`${routes.v4.emails}/send`,{to:to,from_email:from_email,from_name:from_name,cc:cc,bcc:bcc,subject:subject,content:content}).then(r=>{if(r.status!=="success"){dialog({message:r.message,type:"error"});return}dialog({message:__("Message sent!","groundhogg")});onSend({...r,email:{to:to,from_email:from_email,from_name:from_name,cc:cc,bcc:bcc,subject:subject,content:content}});close()}).catch(e=>{dialog({message:e.message,type:"error"});State.set({sending:false});morph()});return false}},[OwnerPicker({label:"From:",id:"composed-from",selected:[State.from_user],multiple:false,allow0:false,itemDisplay:u=>`${u.data.display_name} &lt;${u.data.user_email}&gt;`,onChange:item=>{State.set({form_user:item.id,from_email:getOwner(item.id).data.user_email,from_name:getOwner(item.id).data.display_name})}}),Div({className:"display-flex gap-5 align-center"},[EmailAddressPicker({label:"To",key:"to"}),State.cc.length||State.showCC?null:An({id:"show-cc",onClick:e=>{State.set({showCC:true});morph()}},"CC"),State.bcc.length||State.showBCC?null:An({id:"show-bcc",onClick:e=>{State.set({showBCC:true});morph()}},"BCC")]),State.cc.length||State.showCC?EmailAddressPicker({label:"CC",key:"cc"}):null,State.bcc.length||State.showBCC?EmailAddressPicker({label:"BCC",key:"bcc"}):null,Input({id:"composed-subject-line",name:"composed_subject_line",required:true,placeholder:__("Subject line..."),value:State.subject,onInput:e=>State.set({subject:e.target.value})}),TinyMCE({id:"composed-content",value:State.content,config:{replacements:true,savedReplies:true,media:true,quicktags:false,tinymce:{height:300}},onChange:content=>State.set({content:content})}),Div({className:"display-flex gap-5 flex-end"},[Button({className:"gh-button danger text",disabled:State.sending,onClick:e=>close()},__("Discard")),Button({type:"submit",className:"gh-button primary",disabled:State.sending},State.sending?Span({className:"gh-spinner"}):__("Send"))])])})};const emailModal=(props,onSend=()=>{})=>{return EmailModal(props,onSend)};const EmailTemplateModal=async(contactId,onSend=()=>{})=>{let contactIds,title;if(Array.isArray(contactId)){contactIds=contactId;title=sprintf(__("Select an email to send to %s contacts","groundhogg"),contactIds.length)}else if(typeof contactId==="object"){let contact=contactId;contactIds=[contact.ID];title=sprintf(__("Select an email to send to %s","groundhogg"),contact.data.full_name.trim()||contact.data.email)}else{let contact=await Groundhogg.stores.contacts.maybeFetchItem(contactId);contactIds=[contact.ID];title=sprintf(__("Select an email to send to %s","groundhogg"),contact.data.full_name.trim()||contact.data.email)}const State=Groundhogg.createState({email:null});MakeEl.Modal({},({morph,close})=>MakeEl.Div({id:"send-email-dialog"},[`<h3>${title}</h3>`,MakeEl.ItemPicker({id:`select-email`,noneSelected:__("Select an email to send...","groundhogg"),selected:State.email?{id:State.email.ID,text:State.email.data.title}:[],multiple:false,style:{flexGrow:1},fetchOptions:search=>{return EmailsStore.fetchItems({search:search,status:"ready"}).then(emails=>emails.map(({ID,data})=>({id:ID,text:data.title})))},onChange:item=>{if(!item){State.set({email:null})}else{let email=EmailsStore.get(item.id);State.set({email:email})}morph()}}),State.email?MakeEl.Div({className:"gh-panel outlined"},Groundhogg.components.EmailPreview({...State.email.context,content:State.email.context.built})):null,State.email?MakeEl.Button({id:"send-email",className:"gh-button primary medium",onClick:e=>{e.currentTarget.disabled=true;e.currentTarget.innerHTML=`<span class="gh-spinner"></span>`;EmailsStore.send(State.email.ID,{to:contactIds}).then(r=>{dialog({message:__("Email sent!")});close();onSend(r)}).catch(e=>{dialog({type:"error",message:e.message});morph()})}},__("Send email now!","groundhogg")):null]))};const makeInput=(selector,{inputProps:inputProps={},value:value="",onChange:onChange=()=>{},replaceWith:replaceWith=()=>{}})=>{inputProps={id:uuid(),value:value,...inputProps};$(selector).replaceWith(input(inputProps));$(`#${inputProps.id}`).focus().on("blur keydown",e=>{if(e.type==="keydown"&&e.key!=="Enter"){return}value=e.target.value;onChange(value);$(`#${inputProps.id}`).replaceWith(replaceWith(value))})};const fileUploader=({action:action="",nonce:nonce="",accept:accept="",multiple:multiple=true,fileName:fileName="file-upload",beforeUpload:beforeUpload=()=>{},onUpload:onUpload=()=>{}})=>{return modal({width:600,dialogClasses:"gh-media-uploader",content:`
     210      `};const onMount=({close,setContent})=>{const reMount=()=>{setContent(form());onMount({close:close,setContent:setContent})};tooltip(".use-quick-add",{content:__("Use quick-add form","groundhogg")});tooltip(".use-form",{content:__("Use internal form","groundhogg")});$(".use-form").on("click",e=>{method="form";reMount()});$(".use-quick-add").on("click",e=>{method="quick-add";reMount()});$(`.${prefix}-cancel`).on("click",close);if(method=="quick-add"){quickAddForm(`#${prefix}-quick-add-form`,{prefix:prefix,additionalFields:additionalFields,additionalFieldsOnMount:additionalFieldsOnMount,onCreate:c=>{close();onCreate(c)}})}else{$(`#${prefix}-select-form`).ghPicker({endpoint:FormsStore.route,width:"100%",placeholder:__("Type to search...","groundhogg"),data:[{id:"",text:""},...FormsStore.getItems().map(f=>({id:f.ID,text:f.name,selected:selectedForm&&f.ID==selectedForm.ID}))],getParams:q=>({...q,search:q.term,active:true}),getResults:({items})=>{FormsStore.itemsFetched(items);return items.map(f=>({id:f.ID,text:f.name}))}}).on("select2:select",e=>{selectedForm=FormsStore.get(e.params.data.id);reMount()});if(selectedForm){$(".quick-add-wrap form.gh-form").on("submit",e=>{e.preventDefault();var $form=$(e.currentTarget);handleInternalFormSubmit(selectedForm.ID,$form,c=>{close();onCreate(c)})})}}};return modal({content:form(),onOpen:onMount})};const EmailModal=(props,onSend=()=>{})=>{const State=Groundhogg.createState({to:[],from_user:currentUser.ID,from_name:currentUser.data.display_name,from_email:currentUser.data.user_email,cc:[],showCC:false,bcc:[],showBCC:false,subject:"",content:"",sending:false,...props});const EmailAddressPicker=({label="",key=""})=>ItemPicker({id:`composed-${key}`,label:`${label}:`,style:{flexGrow:1},noneSelected:`${label}...`,tags:true,selected:State[key].map(v=>({id:v,text:v})),fetchOptions:search=>ContactsStore.fetchItems({search:search}).then(items=>items.map(item=>({id:item.data.email,text:item.data.email}))),isValidSelection:isValidEmail,onChange:items=>State.set({[key]:items.map(item=>item.id)})});return Modal({className:"send-email",dialogClasses:"gh-panel",overlay:false,onClose:()=>{wp.editor.remove("composed-content")}},({close,morph:realMorph})=>{const morph=()=>realMorph({});return Form({id:"compose-email-form",className:"display-flex column gap-10",onSubmit:e=>{e.preventDefault();const{to,from_email,from_name,cc,bcc,subject,content}=State;if(!content){errorDialog({message:"Please add a message."});return false}if(!to.length){errorDialog({message:"Please add a least one recipient."});return false}State.set({sending:true});morph();post(`${routes.v4.emails}/send`,{to:to,from_email:from_email,from_name:from_name,cc:cc,bcc:bcc,subject:subject,content:content}).then(r=>{if(r.status!=="success"){dialog({message:r.message,type:"error"});return}dialog({message:__("Message sent!","groundhogg")});onSend({...r,email:{to:to,from_email:from_email,from_name:from_name,cc:cc,bcc:bcc,subject:subject,content:content}});close()}).catch(e=>{dialog({message:e.message,type:"error"});State.set({sending:false});morph()});return false}},[OwnerPicker({label:"From:",id:"composed-from",selected:[State.from_user],multiple:false,allow0:false,itemDisplay:u=>`${u.data.display_name} &lt;${u.data.user_email}&gt;`,onChange:item=>{State.set({form_user:item.id,from_email:getOwner(item.id).data.user_email,from_name:getOwner(item.id).data.display_name})}}),Div({className:"display-flex gap-5 align-center"},[EmailAddressPicker({label:"To",key:"to"}),State.cc.length||State.showCC?null:An({id:"show-cc",onClick:e=>{State.set({showCC:true});morph()}},"CC"),State.bcc.length||State.showBCC?null:An({id:"show-bcc",onClick:e=>{State.set({showBCC:true});morph()}},"BCC")]),State.cc.length||State.showCC?EmailAddressPicker({label:"CC",key:"cc"}):null,State.bcc.length||State.showBCC?EmailAddressPicker({label:"BCC",key:"bcc"}):null,Input({id:"composed-subject-line",name:"composed_subject_line",required:true,placeholder:__("Subject line..."),value:State.subject,onInput:e=>State.set({subject:e.target.value})}),TinyMCE({id:"composed-content",value:State.content,config:{replacements:true,savedReplies:true,media:true,quicktags:false,tinymce:{height:300}},onChange:content=>State.set({content:content})}),Div({className:"display-flex gap-5 flex-end"},[Button({className:"gh-button danger text",disabled:State.sending,onClick:e=>close()},__("Discard")),Button({type:"submit",className:"gh-button primary",disabled:State.sending},State.sending?Span({className:"gh-spinner"}):__("Send"))])])})};const emailModal=(props,onSend=()=>{})=>{return EmailModal(props,onSend)};const EmailTemplateModal=async(contactId,onSend=()=>{})=>{let contactIds,title;if(Array.isArray(contactId)){contactIds=contactId;title=sprintf(__("Select an email to send to %s contacts","groundhogg"),contactIds.length)}else if(typeof contactId==="object"){let contact=contactId;contactIds=[contact.ID];title=sprintf(__("Select an email to send to %s","groundhogg"),contact.data.full_name.trim()||contact.data.email)}else{let contact=await Groundhogg.stores.contacts.maybeFetchItem(contactId);contactIds=[contact.ID];title=sprintf(__("Select an email to send to %s","groundhogg"),contact.data.full_name.trim()||contact.data.email)}const State=Groundhogg.createState({email:null});MakeEl.Modal({},({morph,close})=>MakeEl.Div({id:"send-email-dialog"},[`<h3>${title}</h3>`,MakeEl.ItemPicker({id:`select-email`,noneSelected:__("Select an email to send...","groundhogg"),selected:State.email?{id:State.email.ID,text:State.email.data.title}:[],multiple:false,style:{flexGrow:1},fetchOptions:search=>{return EmailsStore.fetchItems({search:search,status:"ready"}).then(emails=>emails.map(({ID,data})=>({id:ID,text:data.title})))},onChange:item=>{if(!item){State.set({email:null})}else{let email=EmailsStore.get(item.id);State.set({email:email})}morph()}}),State.email?MakeEl.Div({className:"gh-panel outlined"},Groundhogg.components.EmailPreview({...State.email.context,content:State.email.context.built})):null,State.email?MakeEl.Button({id:"send-email",className:"gh-button primary medium",onClick:e=>{e.currentTarget.disabled=true;e.currentTarget.innerHTML=`<span class="gh-spinner"></span>`;EmailsStore.send(State.email.ID,{to:contactIds}).then(r=>{dialog({message:__("Email sent!")});close();onSend(r)}).catch(e=>{dialog({type:"error",message:e.message});morph()})}},__("Send email now!","groundhogg")):null]))};const makeInput=(selector,{inputProps={},value="",onChange=()=>{},replaceWith=()=>{}})=>{inputProps={id:uuid(),value:value,...inputProps};$(selector).replaceWith(input(inputProps));$(`#${inputProps.id}`).focus().on("blur keydown",e=>{if(e.type==="keydown"&&e.key!=="Enter"){return}value=e.target.value;onChange(value);$(`#${inputProps.id}`).replaceWith(replaceWith(value))})};const fileUploader=({action="",nonce="",accept="",multiple=true,fileName="file-upload",beforeUpload=()=>{},onUpload=()=>{}})=>{return modal({width:600,dialogClasses:"gh-media-uploader",content:`
    211211          ${input({type:"file",id:"upload-file-input",name:"files"+(multiple?"[]":""),className:"hidden",accept:accept,multiple:multiple})}
    212212          <div class="droppable-handler">
     
    216216      <div id="uploading-files"></div>
    217217      <div id="uploaded-files"></div>
    218       `,onOpen:({close})=>{let file=null;let filesToUpload=[];let filesUploaded=[];let uploading=false;const pushFiles=()=>{renderUploadingFiles();file=filesToUpload.pop();if(!file){uploading=false;return}uploading=true;let fd=new FormData;fd.append(fileName,file,file.name);fd.append("gh_admin_ajax_nonce",Groundhogg.nonces._adminajax);fd.append("action",action);beforeUpload(fd);setTimeout(()=>{fetch(ajaxurl,{method:"POST",credentials:"same-origin",body:fd}).then(r=>{if(!r.ok){dialog({message:__("Something when wrong..."),type:"error"});return}return r.json()}).then(r=>{if(!r.success){dialog({message:r.data[0].message,type:"error"});pushFiles();return}onUpload(r,file);filesUploaded.unshift(file);renderUploadedFiles();pushFiles()})},2e3)};const renderUploadingFiles=()=>{$("#uploading-files").html(filesToUpload.map(f=>`<div class="file"><span class="hourglass">⌛</span> ${f.name}</div>`))};const renderUploadedFiles=()=>{$("#uploaded-files").html(filesUploaded.map(f=>`<div class="file">✅ ${f.name}</div>`))};const addFiles=files=>{filesToUpload.push(...files);if(!uploading){pushFiles()}};const $input=$("#upload-file-input");$input.on("change",e=>{addFiles(e.target.files)});$("#select-files").on("click",e=>{e.preventDefault();$input.click()});const $droppable=$(".droppable-handler");$droppable.on("dragover",e=>{e.preventDefault();$droppable.addClass("dragover")}).on("dragleave",e=>{$droppable.removeClass("dragover")}).on("drop",e=>{e.preventDefault();$droppable.removeClass("dragover");let{dataTransfer}=e.originalEvent;addFiles(dataTransfer.files)})}})};const EmailPreviewModal=async(emailId,{height:height=window.innerHeight*.85,width:width=900})=>{const{close}=loadingModal();let email;try{email=await EmailsStore.maybeFetchItem(emailId)}catch(err){close();throw err}const{from_avatar,from_email,from_name,subject,built:content}=email.context;close();return ModalFrame({frameAttributes:{className:"gh-modal-frame gh-email-preview-modal"}},({close})=>Div({style:{width:`${width}px`,height:`${height}px`}},EmailPreview({close:close,from_avatar:from_avatar,from_email:from_email,from_name:from_name,subject:subject,content:content})))};const EmailPreview=({close:close=false,from_avatar,from_email,from_name,subject,content})=>{return Div({className:"email-preview"},[Div({className:"from-preview display-flex gap-20 has-box-shadow"},[makeEl("img",{src:from_avatar,className:"from-avatar",height:40,width:40,style:{borderRadius:"50%"}}),Div({className:"subject-and-from"},[`<h2>${subject}</h2>`,`<span class="from-name">${from_name}</span> <span class="from-email">&lt;${from_email}&gt;</span>`]),close!==false?Button({className:"gh-button secondary icon text",style:{marginLeft:"auto"},onClick:close},Dashicon("no-alt")):null]),Iframe({id:"desktop-preview-iframe"},content)])};$(()=>{$(document).on("click","table.wp-list-table .gh-email-preview",e=>{e.preventDefault();EmailPreviewModal(parseInt($(e.currentTarget).closest("tr").attr("id")),{})})});const ImagePicker=({multiple:multiple=false,title:title=__("Select a image to upload"),selectText:selectText=__("Use this image"),onChange:onChange=attachment=>{}})=>{let file_frame=wp.media({title:title,button:{text:selectText},multiple:multiple});file_frame.on("select",function(){let attachment=file_frame.state().get("selection").first().toJSON();onChange(attachment)});file_frame.open()};const ImageInput=({id,name:name="src",onChange,value:value=""})=>{const handleChange=(value,attachment=null)=>{onChange(value,attachment);morphdom(document.getElementById(id),ImageInput({id:id,name:name,onChange:onChange,value:value}))};return Div({id:id,className:"image-picker"},[value?Div({id:`${id}-preview`,className:"image-input-preview",style:{backgroundImage:`url(${value})`},onClick:e=>{e.preventDefault();ImagePicker({multiple:false,onChange:attachment=>handleChange(attachment.url,attachment)})}}):null,InputGroup([Input({type:"text",id:`${id}-src`,value:value,className:"control full-width",name:name,onChange:e=>{handleChange(e.target.value,null)}}),Button({id:`${id}-select`,className:"gh-button secondary icon",onClick:e=>{e.preventDefault();ImagePicker({multiple:false,onChange:attachment=>handleChange(attachment.url,attachment)})}},icons.image)])])};const FeedbackModal=({subject:subject="",message:message="",onSubmit:onSubmit=r=>{}})=>{const State=Groundhogg.createState({subject:subject,message:message,submitting:false});ModalWithHeader({width:"400px",header:"Send Feedback"},({close,morph})=>Form({className:"display-flex column gap-5",onSubmit:e=>{e.preventDefault();State.set({submitting:true});morph();Groundhogg.api.ajax({action:"gh_plugin_feedback",subject:State.subject,message:State.message}).then(r=>{onSubmit(r);dialog({message:"Thanks for your feedback!"});close()});return false}},[Label({for:"feedback-subject"},["What feature are you submitting feedback for?"]),Input({id:"feedback-subject",value:State.subject,required:true,onInput:e=>State.set({subject:e.target.value})}),Div(),Label({for:"feedback-message"},["What is your feedback? Be as descriptive as possible."]),Textarea({id:"feedback-message",value:State.message,required:true,rows:4,onInput:e=>State.set({message:e.target.value})}),Button({className:"gh-button primary",type:"submit",disabled:State.submitting},"Send feedback"),Pg({},"Your email address will be collected to validate your feedback, but will not be used beyond that.")]))};$(document).on("click","a.feedback-modal",e=>{e.preventDefault();const{subject:subject="",message:message=""}=e.currentTarget.dataset;FeedbackModal({subject:subject,message:message})});const ContactPhone=(icon,number,extension="")=>number?Span({className:"contact-phone"},[icon,An({href:`tel:${number}`},number),extension?Span({className:"ext"},` x${extension}`):null]):null;const ContactListItem=(item,{extra:extra=item=>null,...props}={})=>{let allTags=jsonCopy(item.tags);let showTags=allTags.splice(0,10);const{ID}=item;const{full_name,gravatar,date_created,email}=item.data;const{primary_phone:primary_phone="",primary_phone_extension:primary_phone_extension="",mobile_phone:mobile_phone="",company_phone:company_phone="",company_phone_extension:company_phone_extension=""}=item.meta;return Div({className:`contact-list-item`,id:`contact-list-item-${ID}`,dataId:ID,...props},[Div({className:"display-flex gap-10"},[Img({className:"avatar",src:gravatar,alt:"avatar"}),Div({className:"display-flex column"},[Div({},[makeEl("h4",{style:{margin:0}},full_name),Span({className:"subscribed"},`&nbsp;— ${sprintf(__("Subscribed %s"),`<abbr title="${formatDateTime(date_created)}">${sprintf(__("%s ago "),item.i18n.created)}</abbr>`)}`)]),Div({},[An({href:`mailto:${email}`},email),Span({},[" — ",Span({className:`gh-text ${item.is_marketable?"green":"red"}`},Groundhogg.filters.optin_status[item.data.optin_status])])])])]),Div({className:"show-on-hover"},[primary_phone||company_phone||mobile_phone?Div({className:"contact-phones"},[ContactPhone(icons.mobile,mobile_phone),ContactPhone(icons.phone,primary_phone,primary_phone_extension),ContactPhone(icons.phone,company_phone,company_phone_extension)]):null,Div({className:"gh-tags"},[...showTags.map(tag=>Span({className:"gh-tag"},tag.data.tag_name)),allTags.length?Span({},sprintf("and %d more...",allTags.length)):null]),maybeCall(extra,item)])])};const ContactList=(contacts=[],{noContacts:noContacts=()=>null,itemProps:itemProps={}}={})=>{if(!contacts.length){return maybeCall(noContacts)}return Div({className:"contact-list"},contacts.map(contact=>ContactListItem(contact,maybeCall(itemProps,contact))))};const QuickSearch=({itemProps:itemProps={},queryOverrides:queryOverrides={}}={})=>{const State=Groundhogg.createState({search:"",searched:false,results:[],loaded:false});const fetchResults=async()=>{let results=await ContactsStore.fetchItems({search:State.search,orderby:"date_created",order:"DESC",limit:5,...queryOverrides});State.set({results:results,searched:true,loaded:true})};return Div({id:"quick-search-wrap"},morph=>{if(!State.loaded){fetchResults().then(morph)}const updateResults=debounce(async()=>{await fetchResults();morph()},300);return Fragment([Form({action:adminPageURL("gh_contacts")},[Input({type:"hidden",name:"page",value:"gh_contacts"}),Input({id:"quick-search-input",placeholder:__("Search by name or email...","groundhogg"),type:"search",name:"s",value:State.search,onInput:e=>{State.set({search:e.target.value});updateResults()}})]),State.loaded?null:Skeleton({},["full","full","full"]),State.results.length?ContactList(State.results,{itemProps:item=>({className:"contact-list-item clickable",onClick:e=>{window.open(item.admin,"_self")},...maybeCall(itemProps,item)})}):null,State.results.length===0&&State.searched?Pg({style:{textAlign:"center"}},__("No contacts found for the current search","groundhogg")):null])})};const Panel=({id,name,collapsed:collapsed=false,hidden:hidden=false,onCollapse:onCollapse=id=>{}},content)=>{if(hidden){return null}return Div({id:`${id}-panel`,className:`gh-panel ${collapsed?"closed":""}`},[Div({className:`gh-panel-header`},[H2({},name),Button({className:"toggle-indicator",onClick:e=>{onCollapse(id)}})]),collapsed?null:maybeCall(content)])};const Panels=overrides=>({...Groundhogg.createRegistry({}),storagePrefix:"gh-panels",collapse(id){if(!this.isCollapsed(id)){this.toggleCollapse(id)}},expand(id){if(this.isCollapsed(id)){this.toggleCollapse(id)}},hide(id){if(!this.isHidden(id)){this.toggleHidden(id)}},show(id){if(this.isHidden(id)){this.toggleHidden(id)}},togglePanel(id,suffix){let panels=this.getPanelIds(suffix);if(panels.includes(id)){panels.splice(panels.indexOf(id),1)}else{panels.push(id)}localStorage.setItem(`${this.storagePrefix}-${suffix}`,JSON.stringify(panels))},toggleHidden(id){this.togglePanel(id,"hidden")},toggleCollapse(id){this.togglePanel(id,"collapsed")},getPanelIds(suffix){return JSON.parse(localStorage.getItem(`${this.storagePrefix}-${suffix}`))||[]},getHiddenPanelIds(){return this.getPanelIds("hidden")},getCollapsedPanelIds(){return this.getPanelIds("collapsed")},isHidden(id){return this.getHiddenPanelIds().includes(id)},isCollapsed(id){return this.getCollapsedPanelIds().includes(id)},PanelControls(){return Div({},[...this.map((item,id)=>Div({className:"display-flex gap-10",style:{marginBottom:"10px"}},[Toggle({checked:!this.isHidden(id),id:`toggle-${id}`,onChange:e=>{this.toggleHidden(id)}}),Label({for:`toggle-${id}`},item.name)]))])},Panel(id){let{content,...panel}=this.get(id);return Panel({id:id,...panel,collapsed:this.isCollapsed(id),hidden:this.isHidden(id),onCollapse:id=>{this.toggleCollapse(id);morphdom(document.getElementById(`${id}-panel`),this.Panel(id))}},content)},Panels(){return Div({className:"display-flex column gap-20",id:this.storagePrefix},this.keys().map(id=>this.Panel(id)))},...overrides});const Relationships=({title:title="",id,store,child_type:child_type="",parent_type:parent_type="",renderItem:renderItem=item=>{},onAddItem:onAddItem=(r,j)=>{}})=>{const rel_type_key=child_type?"child_type":"parent_type";const rel_type=child_type||parent_type;const rel_id_key=child_type?"child_id":"parent_id";const State=Groundhogg.createState({loaded:false,items:[]});const fetchRelationships=()=>store.fetchRelationships(id,{[rel_type_key]:rel_type}).then(items=>State.set({items:items,loaded:true}));const deleteRelationship=itemId=>store.deleteRelationships(id,{[rel_type_key]:rel_type,[rel_id_key]:itemId}).then(()=>State.set({items:State.items.filter(item=>item.ID!==itemId)}));const createRelationship=item=>store.createRelationships(id,{[rel_type_key]:rel_type,[rel_id_key]:item.ID}).then(()=>State.set({items:[...State.items,item]}));return Div({id:`${rel_type_key}-${rel_type}-rel-of-${id}`,className:`display-flex column relationship-editor ${rel_type_key}-${rel_type}`},morph=>{const handleDeleteRelationship=itemId=>deleteRelationship(itemId).then(morph);if(!State.loaded){fetchRelationships().then(morph);return Skeleton({},["full","full","full"])}const AddRelButton=()=>Button({id:`add-${rel_type_key}-${rel_type}-rel-for-${id}`,className:"gh-button secondary text icon",onClick:e=>{let promise=new Promise((resolve,reject)=>onAddItem(resolve,reject,State));promise.then(item=>createRelationship(item).then(morph))}},[Dashicon("plus-alt2"),ToolTip(__("Add relationship","groundhogg"),"left")]);return Fragment([title?Div({className:"space-between"},[H4({},title),AddRelButton()]):null,...State.items.map(item=>renderItem({...item,onDelete:handleDeleteRelationship})),title?null:Div({className:"display-flex flex-end"},AddRelButton())])})};const OwnerPicker=({id:id="select-owners",selected:selected=[],onChange:onChange=ids=>{},allow0:allow0=true,itemDisplay:itemDisplay=user=>user.data.display_name,multiple:multiple=true,...overrides})=>ItemPicker({id:`select-users`,noneSelected:__("Select a user...","groundhogg"),selected:selected.map(user_id=>{if(user_id==0&&allow0){return{id:0,text:__("The contact owner","groundhogg")}}return{id:user_id,text:itemDisplay(getOwner(user_id))}}),multiple:multiple,style:{flexGrow:1},isValidSelection:id=>id===0||getOwner(id),fetchOptions:search=>{search=new RegExp(search,"i");let options=Groundhogg.filters.owners.map(u=>({id:u.ID,text:itemDisplay(u)}));if(allow0){options.push({id:0,text:__("The contact owner","groundhogg")})}options=options.filter(({text})=>text.match(search));return Promise.resolve(options)},onChange:items=>{if(multiple){onChange(items.map(({id})=>id));return}onChange(items)},...overrides});function getClosestRelativeAncestor(element){let parent=element.parentElement;while(parent){if(window.getComputedStyle(parent).position==="relative"){return parent}parent=parent.parentElement}return null}const Tour=(steps,{onFinish:onFinish=()=>{},beforeDismiss:beforeDismiss=({dismiss})=>dismiss(),onDismiss:onDismiss=()=>{},fixed:fixed=false})=>{const State=Groundhogg.createState({current:0,step:null,target:null,relative:null});const currentStep=()=>steps[State.current];const removeSteps=()=>{document.querySelectorAll(".tour-prompt-container").forEach(el=>el.remove());document.querySelectorAll(".tour-prompt").forEach(el=>el.remove());document.querySelectorAll(".tour-highlighted").forEach(el=>el.classList.remove("tour-highlighted"))};const remove=()=>{removeSteps();document.removeEventListener("resize",rePositionStep);document.removeEventListener("scroll",rePositionStep)};const dismiss=async()=>{remove();onDismiss()};const next=()=>{const{onNext:onNext=()=>{}}=currentStep();onNext();if(State.current+1>=steps.length){remove();onFinish(true);return}State.current++;showStep()};const prev=()=>{const{onPrev:onPrev=()=>{}}=currentStep();onPrev();if(State.current<=0){return}State.current--;showStep()};const showStep=()=>{removeSteps();positionStep()};function rePositionStep(){let{position}=currentStep();let{target,relative,step,windowEl}=State;const targetPos=target.getBoundingClientRect();const relativePos=relative.getBoundingClientRect();const stepPos=step.getBoundingClientRect();const gap=20;if(fixed){windowEl.style.height=`${targetPos.height+gap*2}px`;windowEl.style.width=`${targetPos.width+gap*2}px`;windowEl.style.borderWidth=`${Math.round(targetPos.y)-gap}px ${Math.round(window.innerWidth-targetPos.x)-gap}px ${Math.round(window.innerHeight-targetPos.y)-gap}px ${Math.round(targetPos.x)-gap}px`;switch(position){case"right":step.style.left=`${targetPos.x+targetPos.width+gap}px`;step.style.top=`${targetPos.y}px`;break;case"left":step.style.left=`${targetPos.x-stepPos.width-gap}px`;step.style.top=`${targetPos.y}px`;break;case"above":step.style.left=`${targetPos.x}px`;step.style.top=`${targetPos.y-stepPos.height-gap}px`;break;case"below":step.style.left=`${targetPos.x}px`;step.style.top=`${targetPos.y+targetPos.height+gap}px`;break;case"below-left":step.style.left=`${targetPos.x+targetPos.width-stepPos.width}px`;step.style.top=`${targetPos.y+targetPos.height+gap}px`;break}return}switch(position){case"right":step.style.left=`${targetPos.right-relativePos.left+gap}px`;step.style.top=`${targetPos.top-relativePos.top}px`;break;case"left":step.style.left=`${targetPos.left-relativePos.left-stepPos.width-gap}px`;step.style.top=`${targetPos.top-relativePos.top}px`;break;case"above":step.style.left=`${targetPos.left-relativePos.left}px`;step.style.top=`${targetPos.top-relativePos.top-stepPos.height-gap}px`;break;case"below":step.style.left=`${targetPos.left-relativePos.left}px`;step.style.top=`${targetPos.bottom-relativePos.top+gap}px`;break;case"below-left":step.style.left=`${targetPos.right-relativePos.left-stepPos.width}px`;step.style.top=`${targetPos.bottom-relativePos.top+gap}px`;break}}function positionStep(){let tourEl=TourStep();let windowEl=tourEl.querySelector(".tour-window");let stepEl=tourEl.querySelector(".tour-prompt");let{target,relative,onInit:onInit=()=>{},onBefore:onBefore=()=>{}}=currentStep();target=document.querySelector(target);if(!target){next();return}if(fixed){relative=document.body}else if(relative){relative=target.closest(relative)}else{relative=getClosestRelativeAncestor(target)}stepEl.style.position=fixed?"fixed":"absolute";if(fixed){relative.append(tourEl)}else{target.classList.add("tour-highlighted");relative.append(stepEl)}target.scrollIntoView({behavior:"instant",block:"center",inline:"center"});onBefore({next:next,prev:prev,target:target,relative:relative,step:stepEl,windowEl:windowEl,currentStep:currentStep});State.set({step:stepEl,windowEl:windowEl,target:target,relative:relative});rePositionStep();onInit({next:next,prev:prev,target:target,relative:relative,step:stepEl,windowEl:windowEl,currentStep:currentStep});stepEl.querySelector("#tour-next").focus()}const TourStep=()=>MakeEl.Div({className:"tour-prompt-container"},[fixed?MakeEl.Div({className:"tour-window"},[MakeEl.Div({className:"tour-window-shadow",onClick:next})]):null,MakeEl.Div({className:`tour-prompt ${currentStep().position}`,style:{padding:"10px",width:"200px"}},[MakeEl.Button({className:"dismiss",onClick:e=>{beforeDismiss({dismiss:dismiss,State:State})}},MakeEl.Dashicon("no-alt")),MakeEl.Div({},currentStep().prompt),MakeEl.Div({className:"display-flex flex-end gap-5 space-above-10"},[State.current>0?MakeEl.Button({id:"tour-prev",className:"gh-button small secondary text prev-step",onClick:()=>prev()},"Prev"):null,currentStep().showNext===false?null:MakeEl.Button({id:"tour-next",className:`gh-button small ${State.current<steps.length-1?"secondary":"primary"} next-step`,onClick:()=>next()},State.current<steps.length-1?"Next":"Finish")])])]);document.addEventListener("resize",rePositionStep);document.addEventListener("scroll",rePositionStep);positionStep()};Groundhogg.components={QuickSearch:QuickSearch,addContactModal:addContactModal,internalForm:internalForm,betterTagPicker:betterTagPicker,quickAddForm:quickAddForm,selectContactModal:selectContactModal,quickEditContactModal:quickEditContactModal,makeInput:makeInput,emailModal:emailModal,EmailTemplateModal:EmailTemplateModal,fileUploader:fileUploader,EmailPreview:EmailPreview,EmailPreviewModal:EmailPreviewModal,ImageInput:ImageInput,ImagePicker:ImagePicker,FeedbackModal:FeedbackModal,ContactList:ContactList,ContactListItem:ContactListItem,Panel:Panel,Panels:Panels,Relationships:Relationships,OwnerPicker:OwnerPicker,Tour:Tour}})(jQuery);
     218      `,onOpen:({close})=>{let file=null;let filesToUpload=[];let filesUploaded=[];let uploading=false;const pushFiles=()=>{renderUploadingFiles();file=filesToUpload.pop();if(!file){uploading=false;return}uploading=true;let fd=new FormData;fd.append(fileName,file,file.name);fd.append("gh_admin_ajax_nonce",Groundhogg.nonces._adminajax);fd.append("action",action);beforeUpload(fd);setTimeout(()=>{fetch(ajaxurl,{method:"POST",credentials:"same-origin",body:fd}).then(r=>{if(!r.ok){dialog({message:__("Something when wrong..."),type:"error"});return}return r.json()}).then(r=>{if(!r.success){dialog({message:r.data[0].message,type:"error"});pushFiles();return}onUpload(r,file);filesUploaded.unshift(file);renderUploadedFiles();pushFiles()})},2e3)};const renderUploadingFiles=()=>{$("#uploading-files").html(filesToUpload.map(f=>`<div class="file"><span class="hourglass">⌛</span> ${f.name}</div>`))};const renderUploadedFiles=()=>{$("#uploaded-files").html(filesUploaded.map(f=>`<div class="file">✅ ${f.name}</div>`))};const addFiles=files=>{filesToUpload.push(...files);if(!uploading){pushFiles()}};const $input=$("#upload-file-input");$input.on("change",e=>{addFiles(e.target.files)});$("#select-files").on("click",e=>{e.preventDefault();$input.click()});const $droppable=$(".droppable-handler");$droppable.on("dragover",e=>{e.preventDefault();$droppable.addClass("dragover")}).on("dragleave",e=>{$droppable.removeClass("dragover")}).on("drop",e=>{e.preventDefault();$droppable.removeClass("dragover");let{dataTransfer}=e.originalEvent;addFiles(dataTransfer.files)})}})};const EmailPreviewModal=async(emailId,{height=window.innerHeight*.85,width=900})=>{const{close}=loadingModal();let email;try{email=await EmailsStore.maybeFetchItem(emailId)}catch(err){close();throw err}const{from_avatar,from_email,from_name,subject,built:content}=email.context;close();return ModalFrame({frameAttributes:{className:"gh-modal-frame gh-email-preview-modal"}},({close})=>Div({style:{width:`${width}px`,height:`${height}px`}},EmailPreview({close:close,from_avatar:from_avatar,from_email:from_email,from_name:from_name,subject:subject,content:content})))};const EmailPreview=({close=false,from_avatar,from_email,from_name,subject,content})=>{return Div({className:"email-preview"},[Div({className:"from-preview display-flex gap-20 has-box-shadow"},[makeEl("img",{src:from_avatar,className:"from-avatar",height:40,width:40,style:{borderRadius:"50%"}}),Div({className:"subject-and-from"},[`<h2>${subject}</h2>`,`<span class="from-name">${from_name}</span> <span class="from-email">&lt;${from_email}&gt;</span>`]),close!==false?Button({className:"gh-button secondary icon text",style:{marginLeft:"auto"},onClick:close},Dashicon("no-alt")):null]),Iframe({id:"desktop-preview-iframe"},content)])};$(()=>{$(document).on("click","a.gh-email-preview",e=>{e.preventDefault();let emailId=e.currentTarget.dataset.id??e.currentTarget.closest("tr").id;EmailPreviewModal(parseInt(emailId),{})})});const ImagePicker=({multiple=false,title=__("Select a image to upload"),selectText=__("Use this image"),onChange=attachment=>{}})=>{let file_frame=wp.media({title:title,button:{text:selectText},multiple:multiple});file_frame.on("select",function(){let attachment=file_frame.state().get("selection").first().toJSON();onChange(attachment)});file_frame.open()};const ImageInput=({id,name="src",onChange,value=""})=>{const handleChange=(value,attachment=null)=>{onChange(value,attachment);morphdom(document.getElementById(id),ImageInput({id:id,name:name,onChange:onChange,value:value}))};return Div({id:id,className:"image-picker"},[value?Div({id:`${id}-preview`,className:"image-input-preview",style:{backgroundImage:`url(${value})`},onClick:e=>{e.preventDefault();ImagePicker({multiple:false,onChange:attachment=>handleChange(attachment.url,attachment)})}}):null,InputGroup([Input({type:"text",id:`${id}-src`,value:value,className:"control full-width",name:name,onChange:e=>{handleChange(e.target.value,null)}}),Button({id:`${id}-select`,className:"gh-button secondary icon",onClick:e=>{e.preventDefault();ImagePicker({multiple:false,onChange:attachment=>handleChange(attachment.url,attachment)})}},icons.image)])])};const FeedbackModal=({subject="",message="",onSubmit=r=>{}})=>{const State=Groundhogg.createState({subject:subject,message:message,submitting:false});ModalWithHeader({width:"400px",header:"Send Feedback"},({close,morph})=>Form({className:"display-flex column gap-5",onSubmit:e=>{e.preventDefault();State.set({submitting:true});morph();Groundhogg.api.ajax({action:"gh_plugin_feedback",subject:State.subject,message:State.message}).then(r=>{onSubmit(r);dialog({message:"Thanks for your feedback!"});close()});return false}},[Label({for:"feedback-subject"},["What feature are you submitting feedback for?"]),Input({id:"feedback-subject",value:State.subject,required:true,onInput:e=>State.set({subject:e.target.value})}),Div(),Label({for:"feedback-message"},["What is your feedback? Be as descriptive as possible."]),Textarea({id:"feedback-message",value:State.message,required:true,rows:4,onInput:e=>State.set({message:e.target.value})}),Button({className:"gh-button primary",type:"submit",disabled:State.submitting},"Send feedback"),Pg({},"Your email address will be collected to validate your feedback, but will not be used beyond that.")]))};$(document).on("click","a.feedback-modal",e=>{e.preventDefault();const{subject="",message=""}=e.currentTarget.dataset;FeedbackModal({subject:subject,message:message})});const ContactPhone=(icon,number,extension="")=>number?Span({className:"contact-phone"},[icon,An({href:`tel:${number}`},number),extension?Span({className:"ext"},` x${extension}`):null]):null;const ContactListItem=(item,{extra=item=>null,...props}={})=>{let allTags=jsonCopy(item.tags);let showTags=allTags.splice(0,10);const{ID}=item;const{full_name,gravatar,date_created,email}=item.data;const{primary_phone="",primary_phone_extension="",mobile_phone="",company_phone="",company_phone_extension=""}=item.meta;return Div({className:`contact-list-item`,id:`contact-list-item-${ID}`,dataId:ID,...props},[Div({className:"display-flex gap-10"},[Img({className:"avatar",src:gravatar,alt:"avatar"}),Div({className:"display-flex column"},[Div({},[makeEl("h4",{style:{margin:0}},full_name),Span({className:"subscribed"},`&nbsp;— ${sprintf(__("Subscribed %s"),`<abbr title="${formatDateTime(date_created)}">${sprintf(__("%s ago "),item.i18n.created)}</abbr>`)}`)]),Div({},[An({href:`mailto:${email}`},email),Span({},[" — ",Span({className:`gh-text ${item.is_marketable?"green":"red"}`},Groundhogg.filters.optin_status[item.data.optin_status])])])])]),Div({className:"show-on-hover"},[primary_phone||company_phone||mobile_phone?Div({className:"contact-phones"},[ContactPhone(icons.mobile,mobile_phone),ContactPhone(icons.phone,primary_phone,primary_phone_extension),ContactPhone(icons.phone,company_phone,company_phone_extension)]):null,Div({className:"gh-tags"},[...showTags.map(tag=>Span({className:"gh-tag"},tag.data.tag_name)),allTags.length?Span({},sprintf("and %d more...",allTags.length)):null]),maybeCall(extra,item)])])};const ContactList=(contacts=[],{noContacts=()=>null,itemProps={}}={})=>{if(!contacts.length){return maybeCall(noContacts)}return Div({className:"contact-list"},contacts.map(contact=>ContactListItem(contact,maybeCall(itemProps,contact))))};const QuickSearch=({itemProps={},queryOverrides={}}={})=>{const State=Groundhogg.createState({search:"",searched:false,results:[],loaded:false});const fetchResults=async()=>{let results=await ContactsStore.fetchItems({search:State.search,orderby:"date_created",order:"DESC",limit:5,...queryOverrides});State.set({results:results,searched:true,loaded:true})};return Div({id:"quick-search-wrap"},morph=>{if(!State.loaded){fetchResults().then(morph)}const updateResults=debounce(async()=>{await fetchResults();morph()},300);return Fragment([Form({action:adminPageURL("gh_contacts")},[Input({type:"hidden",name:"page",value:"gh_contacts"}),Input({id:"quick-search-input",placeholder:__("Search by name or email...","groundhogg"),type:"search",name:"s",value:State.search,onInput:e=>{State.set({search:e.target.value});updateResults()}})]),State.loaded?null:Skeleton({},["full","full","full"]),State.results.length?ContactList(State.results,{itemProps:item=>({className:"contact-list-item clickable",onClick:e=>{window.open(item.admin,"_self")},...maybeCall(itemProps,item)})}):null,State.results.length===0&&State.searched?Pg({style:{textAlign:"center"}},__("No contacts found for the current search","groundhogg")):null])})};const Panel=({id,name,collapsed=false,hidden=false,onCollapse=id=>{}},content)=>{if(hidden){return null}return Div({id:`${id}-panel`,className:`gh-panel ${collapsed?"closed":""}`},[Div({className:`gh-panel-header`},[H2({},name),Button({className:"toggle-indicator",onClick:e=>{onCollapse(id)}})]),collapsed?null:maybeCall(content)])};const Panels=overrides=>({...Groundhogg.createRegistry({}),storagePrefix:"gh-panels",collapse(id){if(!this.isCollapsed(id)){this.toggleCollapse(id)}},expand(id){if(this.isCollapsed(id)){this.toggleCollapse(id)}},hide(id){if(!this.isHidden(id)){this.toggleHidden(id)}},show(id){if(this.isHidden(id)){this.toggleHidden(id)}},togglePanel(id,suffix){let panels=this.getPanelIds(suffix);if(panels.includes(id)){panels.splice(panels.indexOf(id),1)}else{panels.push(id)}localStorage.setItem(`${this.storagePrefix}-${suffix}`,JSON.stringify(panels))},toggleHidden(id){this.togglePanel(id,"hidden")},toggleCollapse(id){this.togglePanel(id,"collapsed")},getPanelIds(suffix){return JSON.parse(localStorage.getItem(`${this.storagePrefix}-${suffix}`))||[]},getHiddenPanelIds(){return this.getPanelIds("hidden")},getCollapsedPanelIds(){return this.getPanelIds("collapsed")},isHidden(id){return this.getHiddenPanelIds().includes(id)},isCollapsed(id){return this.getCollapsedPanelIds().includes(id)},PanelControls(){return Div({},[...this.map((item,id)=>Div({className:"display-flex gap-10",style:{marginBottom:"10px"}},[Toggle({checked:!this.isHidden(id),id:`toggle-${id}`,onChange:e=>{this.toggleHidden(id)}}),Label({for:`toggle-${id}`},item.name)]))])},Panel(id){let{content,...panel}=this.get(id);return Panel({id:id,...panel,collapsed:this.isCollapsed(id),hidden:this.isHidden(id),onCollapse:id=>{this.toggleCollapse(id);morphdom(document.getElementById(`${id}-panel`),this.Panel(id))}},content)},Panels(){return Div({className:"display-flex column gap-20",id:this.storagePrefix},this.keys().map(id=>this.Panel(id)))},...overrides});const Relationships=({title="",id,store,child_type="",parent_type="",renderItem=item=>{},onAddItem=(r,j)=>{}})=>{const rel_type_key=child_type?"child_type":"parent_type";const rel_type=child_type||parent_type;const rel_id_key=child_type?"child_id":"parent_id";const State=Groundhogg.createState({loaded:false,items:[]});const fetchRelationships=()=>store.fetchRelationships(id,{[rel_type_key]:rel_type}).then(items=>State.set({items:items,loaded:true}));const deleteRelationship=itemId=>store.deleteRelationships(id,{[rel_type_key]:rel_type,[rel_id_key]:itemId}).then(()=>State.set({items:State.items.filter(item=>item.ID!==itemId)}));const createRelationship=item=>store.createRelationships(id,{[rel_type_key]:rel_type,[rel_id_key]:item.ID}).then(()=>State.set({items:[...State.items,item]}));return Div({id:`${rel_type_key}-${rel_type}-rel-of-${id}`,className:`display-flex column relationship-editor ${rel_type_key}-${rel_type}`},morph=>{const handleDeleteRelationship=itemId=>deleteRelationship(itemId).then(morph);if(!State.loaded){fetchRelationships().then(morph);return Skeleton({},["full","full","full"])}const AddRelButton=()=>Button({id:`add-${rel_type_key}-${rel_type}-rel-for-${id}`,className:"gh-button secondary text icon",onClick:e=>{let promise=new Promise((resolve,reject)=>onAddItem(resolve,reject,State));promise.then(item=>createRelationship(item).then(morph))}},[Dashicon("plus-alt2"),ToolTip(__("Add relationship","groundhogg"),"left")]);return Fragment([title?Div({className:"space-between"},[H4({},title),AddRelButton()]):null,...State.items.map(item=>renderItem({...item,onDelete:handleDeleteRelationship})),title?null:Div({className:"display-flex flex-end"},AddRelButton())])})};const OwnerPicker=({id="select-owners",selected=[],onChange=ids=>{},allow0=true,itemDisplay=user=>user.data.display_name,multiple=true,...overrides})=>ItemPicker({id:`select-users`,noneSelected:__("Select a user...","groundhogg"),selected:selected.map(user_id=>{if(user_id==0&&allow0){return{id:0,text:__("The contact owner","groundhogg")}}return{id:user_id,text:itemDisplay(getOwner(user_id))}}),multiple:multiple,style:{flexGrow:1},isValidSelection:id=>id===0||getOwner(id),fetchOptions:search=>{search=new RegExp(search,"i");let options=Groundhogg.filters.owners.map(u=>({id:u.ID,text:itemDisplay(u)}));if(allow0){options.push({id:0,text:__("The contact owner","groundhogg")})}options=options.filter(({text})=>text.match(search));return Promise.resolve(options)},onChange:items=>{if(multiple){onChange(items.map(({id})=>id));return}onChange(items)},...overrides});function getClosestRelativeAncestor(element){let parent=element.parentElement;while(parent){if(window.getComputedStyle(parent).position==="relative"){return parent}parent=parent.parentElement}return null}const Tour=(steps,{onFinish=()=>{},beforeDismiss=({dismiss})=>dismiss(),onDismiss=()=>{},fixed=false})=>{const State=Groundhogg.createState({current:0,step:null,target:null,relative:null});const currentStep=()=>steps[State.current];const removeSteps=()=>{document.querySelectorAll(".tour-prompt-container").forEach(el=>el.remove());document.querySelectorAll(".tour-prompt").forEach(el=>el.remove());document.querySelectorAll(".tour-highlighted").forEach(el=>el.classList.remove("tour-highlighted"))};const remove=()=>{removeSteps();document.removeEventListener("resize",rePositionStep);document.removeEventListener("scroll",rePositionStep)};const dismiss=async()=>{remove();onDismiss()};const next=()=>{const{onNext=()=>{}}=currentStep();onNext();if(State.current+1>=steps.length){remove();onFinish(true);return}State.current++;showStep()};const prev=()=>{const{onPrev=()=>{}}=currentStep();onPrev();if(State.current<=0){return}State.current--;showStep()};const showStep=()=>{removeSteps();positionStep()};function rePositionStep(){let{position}=currentStep();let{target,relative,step,windowEl}=State;const targetPos=target.getBoundingClientRect();const relativePos=relative.getBoundingClientRect();const stepPos=step.getBoundingClientRect();const gap=20;if(fixed){windowEl.style.height=`${targetPos.height+gap*2}px`;windowEl.style.width=`${targetPos.width+gap*2}px`;windowEl.style.borderWidth=`${Math.round(targetPos.y)-gap}px ${Math.round(window.innerWidth-targetPos.x)-gap}px ${Math.round(window.innerHeight-targetPos.y)-gap}px ${Math.round(targetPos.x)-gap}px`;switch(position){case"right":step.style.left=`${targetPos.x+targetPos.width+gap}px`;step.style.top=`${targetPos.y}px`;break;case"left":step.style.left=`${targetPos.x-stepPos.width-gap}px`;step.style.top=`${targetPos.y}px`;break;case"above":step.style.left=`${targetPos.x}px`;step.style.top=`${targetPos.y-stepPos.height-gap}px`;break;case"below":step.style.left=`${targetPos.x}px`;step.style.top=`${targetPos.y+targetPos.height+gap}px`;break;case"below-left":step.style.left=`${targetPos.x+targetPos.width-stepPos.width}px`;step.style.top=`${targetPos.y+targetPos.height+gap}px`;break}return}switch(position){case"right":step.style.left=`${targetPos.right-relativePos.left+gap}px`;step.style.top=`${targetPos.top-relativePos.top}px`;break;case"left":step.style.left=`${targetPos.left-relativePos.left-stepPos.width-gap}px`;step.style.top=`${targetPos.top-relativePos.top}px`;break;case"above":step.style.left=`${targetPos.left-relativePos.left}px`;step.style.top=`${targetPos.top-relativePos.top-stepPos.height-gap}px`;break;case"below":step.style.left=`${targetPos.left-relativePos.left}px`;step.style.top=`${targetPos.bottom-relativePos.top+gap}px`;break;case"below-left":step.style.left=`${targetPos.right-relativePos.left-stepPos.width}px`;step.style.top=`${targetPos.bottom-relativePos.top+gap}px`;break}}function positionStep(){let tourEl=TourStep();let windowEl=tourEl.querySelector(".tour-window");let stepEl=tourEl.querySelector(".tour-prompt");let{target,relative,onInit=()=>{},onBefore=()=>{}}=currentStep();target=document.querySelector(target);if(!target){next();return}if(fixed){relative=document.body}else if(relative){relative=target.closest(relative)}else{relative=getClosestRelativeAncestor(target)}stepEl.style.position=fixed?"fixed":"absolute";if(fixed){relative.append(tourEl)}else{target.classList.add("tour-highlighted");relative.append(stepEl)}target.scrollIntoView({behavior:"instant",block:"center",inline:"center"});onBefore({next:next,prev:prev,target:target,relative:relative,step:stepEl,windowEl:windowEl,currentStep:currentStep});State.set({step:stepEl,windowEl:windowEl,target:target,relative:relative});rePositionStep();onInit({next:next,prev:prev,target:target,relative:relative,step:stepEl,windowEl:windowEl,currentStep:currentStep});stepEl.querySelector("#tour-next").focus()}const TourStep=()=>MakeEl.Div({className:"tour-prompt-container"},[fixed?MakeEl.Div({className:"tour-window"},[MakeEl.Div({className:"tour-window-shadow",onClick:next})]):null,MakeEl.Div({className:`tour-prompt ${currentStep().position}`,style:{padding:"10px",width:"200px"}},[MakeEl.Button({className:"dismiss",onClick:e=>{beforeDismiss({dismiss:dismiss,State:State})}},MakeEl.Dashicon("no-alt")),MakeEl.Div({},currentStep().prompt),MakeEl.Div({className:"display-flex flex-end gap-5 space-above-10"},[State.current>0?MakeEl.Button({id:"tour-prev",className:"gh-button small secondary text prev-step",onClick:()=>prev()},"Prev"):null,currentStep().showNext===false?null:MakeEl.Button({id:"tour-next",className:`gh-button small ${State.current<steps.length-1?"secondary":"primary"} next-step`,onClick:()=>next()},State.current<steps.length-1?"Next":"Finish")])])]);document.addEventListener("resize",rePositionStep);document.addEventListener("scroll",rePositionStep);positionStep()};Groundhogg.components={QuickSearch:QuickSearch,addContactModal:addContactModal,internalForm:internalForm,betterTagPicker:betterTagPicker,quickAddForm:quickAddForm,selectContactModal:selectContactModal,quickEditContactModal:quickEditContactModal,makeInput:makeInput,emailModal:emailModal,EmailTemplateModal:EmailTemplateModal,fileUploader:fileUploader,EmailPreview:EmailPreview,EmailPreviewModal:EmailPreviewModal,ImageInput:ImageInput,ImagePicker:ImagePicker,FeedbackModal:FeedbackModal,ContactList:ContactList,ContactListItem:ContactListItem,Panel:Panel,Panels:Panels,Relationships:Relationships,OwnerPicker:OwnerPicker,Tour:Tour}})(jQuery);
  • groundhogg/trunk/assets/js/admin/filters/contacts.js

    r3335438 r3400645  
    24362436  ContactFilterRegistry.registerFilter(CurrentDateCompareFilterFactory('current_time', 'Current Time', 'time', ( time ) => formatTime(`2000-01-01T${time}`) ))
    24372437
     2438  const dayList = {
     2439    0: __('Sunday'),
     2440    1: __('Monday'),
     2441    2: __('Tuesday'),
     2442    3: __('Wednesday'),
     2443    4: __('Thursday'),
     2444    5: __('Friday'),
     2445    6: __('Saturday'),
     2446  }
     2447
     2448  ContactFilterRegistry.registerFilter(createFilter('day_of_week', 'Day of Week', 'date', {
     2449    edit   : ({
     2450      days = [],
     2451      updateFilter,
     2452    }) => {
     2453
     2454      return ItemPicker({
     2455        id          : 'days-of-week-picker',
     2456        noneSelected: 'Select a day',
     2457        fetchOptions: async (search) => assoc2array(dayList).filter(option => option.text.match(new RegExp(search, 'i'))),
     2458        selected    : days.map(day => ( {
     2459          id  : day,
     2460          text: dayList[day],
     2461        } )),
     2462        onChange    : items => {
     2463          updateFilter({
     2464            days: items.map(item => item.id),
     2465          })
     2466        },
     2467      })
     2468
     2469    },
     2470    display: ({ days = [] }) => sprintf(__('Today is a %s'), orList(days.map(day => bold(dayList[day])))),
     2471  }))
     2472
     2473  const dateList = {
     2474    1 : __('1st'),
     2475    2 : __('2nd'),
     2476    3 : __('3rd'),
     2477    4 : __('4th'),
     2478    5 : __('5th'),
     2479    6 : __('6th'),
     2480    7 : __('7th'),
     2481    8 : __('8th'),
     2482    9 : __('9th'),
     2483    10: __('10th'),
     2484    11: __('11th'),
     2485    12: __('12th'),
     2486    13: __('13th'),
     2487    14: __('14th'),
     2488    15: __('15th'),
     2489    16: __('16th'),
     2490    17: __('17th'),
     2491    18: __('18th'),
     2492    19: __('19th'),
     2493    20: __('20th'),
     2494    21: __('21st'),
     2495    22: __('22nd'),
     2496    23: __('23rd'),
     2497    24: __('24th'),
     2498    25: __('25th'),
     2499    26: __('26th'),
     2500    27: __('27th'),
     2501    28: __('28th'),
     2502    29: __('29th'),
     2503    30: __('30th'),
     2504    31: __('31st'),
     2505    0 : __('Last'),
     2506  }
     2507
     2508  ContactFilterRegistry.registerFilter(createFilter('day_of_month', 'Day of Month', 'date', {
     2509    edit   : ({
     2510      dates = [],
     2511      updateFilter,
     2512    }) => {
     2513
     2514      return ItemPicker({
     2515        id          : 'days-of-week-picker',
     2516        noneSelected: 'Select a day',
     2517        fetchOptions: async (search) => assoc2array(dateList).filter(option => option.text.match(new RegExp(search, 'i'))),
     2518        selected    : dates.map(date => ( {
     2519          id  : date,
     2520          text: dateList[date],
     2521        } )),
     2522        onChange    : items => {
     2523          updateFilter({
     2524            dates: items.map(item => item.id),
     2525          })
     2526        },
     2527      })
     2528
     2529    },
     2530    display: ({ dates = [] }) => sprintf(__('Today is the %s of the month'), orList(dates.map(date => bold(dateList[date])))),
     2531  }))
     2532
    24382533  registerFilterGroup( 'submissions', 'Submissions' )
    24392534
     
    25932688  }
    25942689
     2690  ContactFilterRegistry.registerFilter(createPastDateFilter('wp_fusion_activity', 'WP Fusion', 'activity', {
     2691    display: ({
     2692      event_name = '',
     2693      event_name_compare,
     2694      event_value = '',
     2695      event_value_compare,
     2696    }) => {
     2697
     2698      if (!event_name) {
     2699        return 'Any WP Fusion activity'
     2700      }
     2701
     2702      let text = sprintf(`WP Fusion Event: %s`,
     2703        ComparisonsTitleGenerators[event_name_compare](bold('Name'), `<code>${ event_name }</code>`),
     2704      )
     2705
     2706      if (event_value) {
     2707        text += ', ' + ComparisonsTitleGenerators[event_value_compare](bold('Value'), `<code>${ event_value }</code>`)
     2708      }
     2709
     2710      return text
     2711    },
     2712    edit   : ({
     2713      event_name = '',
     2714      event_value = '',
     2715      event_value_compare = 'equals',
     2716      event_name_compare = 'equals',
     2717      updateFilter = () => {},
     2718    }) => {
     2719
     2720      return Fragment([
     2721        MakeEl.Label({ for: 'event-name' }, 'Event Name'),
     2722        MakeEl.InputGroup([
     2723          Select({
     2724            id      : 'event-name-compare',
     2725            name    : 'event_name_compare',
     2726            selected: event_name_compare,
     2727            options : StringComparisons,
     2728            onChange: e => {
     2729              updateFilter({
     2730                event_name_compare: e.target.value,
     2731              })
     2732            },
     2733          }),
     2734          Input({
     2735            id         : 'event-name',
     2736            name       : 'event_name',
     2737            value      : event_name,
     2738            placeholder: 'Event Name',
     2739            onChange   : e => {
     2740              updateFilter({
     2741                event_name: e.target.value,
     2742              })
     2743            },
     2744          }),
     2745        ]),
     2746        MakeEl.Label({ for: 'event-value' }, 'Event Value'),
     2747        MakeEl.InputGroup([
     2748          Select({
     2749            id      : 'event-value-compare',
     2750            selected: event_value_compare,
     2751            options : AllComparisons,
     2752            onChange: e => {
     2753              updateFilter({
     2754                event_value_compare: e.target.value,
     2755              })
     2756            },
     2757          }),
     2758          Input({
     2759            id         : 'event-value',
     2760            value      : event_value,
     2761            placeholder: 'Event value',
     2762            onChange   : e => {
     2763              updateFilter({
     2764                event_value: e.target.value,
     2765              })
     2766            },
     2767          }),
     2768        ]),
     2769      ])
     2770    },
     2771  }, {
     2772    event_name_compare : 'equals',
     2773    event_name         : '',
     2774    event_value_compare: 'equals',
     2775    event_value        : '',
     2776  }))
     2777
    25952778  if (typeof Groundhogg.rawStepTypes.webhook_listener !== 'undefined') {
    25962779    ContactFilterRegistry.registerFilter(createPastDateFilter('webhook_request', 'Webhook Request', 'submissions', {
  • groundhogg/trunk/assets/js/admin/filters/contacts.min.js

    r3335438 r3400645  
    1 (function($){const{input,select,orList,andList,bold,inputRepeater}=Groundhogg.element;const{broadcastPicker,funnelPicker,tagPicker,emailPicker,linkPicker,metaValuePicker,metaPicker,userMetaPicker}=Groundhogg.pickers;const{assoc2array}=Groundhogg.functions;const{broadcasts:BroadcastsStore,emails:EmailsStore,tags:TagsStore,funnels:FunnelsStore,searches:SearchesStore}=Groundhogg.stores;const{sprintf,__,_x,_n}=wp.i18n;const{formatDate,formatDateTime,formatTime}=Groundhogg.formatting;const{Fragment,ItemPicker,Select,Input,Div,makeEl,InputRepeater}=MakeEl;const{Filters,FilterRegistry,createFilter,createGroup,FilterDisplay,createDateFilter,createPastDateFilter,createStringFilter,createNumberFilter,createTimeFilter,unsubReasons}=Groundhogg.filters;const{ComparisonsTitleGenerators,AllComparisons,StringComparisons,NumericComparisons,pastDateRanges,futureDateRanges,allDateRanges}=Groundhogg.filters.comparisons;const ContactFilterRegistry=FilterRegistry({});const uid=function(){return Date.now().toString(36)+Math.random().toString(36).substring(2)};const createFilters=(el="",filters=[],onChange=f=>{console.log(f)})=>({el:el,onChange:onChange,filters:Array.isArray(filters)?filters:[],id:uid(),init(){this.mount()},mount(){let container=document.querySelector(el);container.innerHTML="";document.querySelector(el).appendChild(ContactFilters(this.id,this.filters,this.onChange))}});const ContactFilters=(id,filters,onChange)=>Filters({id:id,filterRegistry:ContactFilterRegistry,filters:filters,onChange:onChange});const ContactFilterDisplay=filters=>FilterDisplay({filters:filters,filterRegistry:ContactFilterRegistry});const registerFilterGroup=(group,name)=>{ContactFilterRegistry.registerGroup(createGroup(group,name))};const registerFilter=(type,group="general",name="",opts={})=>{if(typeof name==="object"){let tempOpts=name;name=tempOpts.name;opts=tempOpts}const{defaults:defaults={},preload:preload=()=>{},view:view=()=>"",edit:edit=()=>"",onMount:onMount=()=>""}=opts;ContactFilterRegistry.registerFilter(createFilter(type,name,group,{display:view,preload:preload,edit:({updateFilter,...filter})=>Fragment([edit(filter)],{onCreate:el=>{setTimeout(()=>{onMount(filter,updateFilter)},50)}})},defaults))};const standardActivityDateFilterOnMount=(filter,updateFilter)=>{$("#filter-date-range, #filter-before, #filter-after, #filter-days").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()});if($el.prop("name")==="date_range"){const $before=$("#filter-before");const $after=$("#filter-after");const $days=$("#filter-days");$before.addClass("hidden");$after.addClass("hidden");$days.addClass("hidden");switch($el.val()){case"between":$before.removeClass("hidden");$after.removeClass("hidden");break;case"day_of":case"after":$after.removeClass("hidden");break;case"before":$before.removeClass("hidden");break;case"x_days":$days.removeClass("hidden");break}}})};const standardActivityDateTitle=(prepend,{date_range,before,after,days:days=0,future:future=false})=>{let ranges=future?futureDateRanges:pastDateRanges;switch(date_range){default:return`${prepend} ${ranges[date_range]?ranges[date_range].replace("X",days).toLowerCase():""}`;case"between":return`${prepend} ${sprintf(_x("between %1$s and %2$s","where %1 and %2 are dates","groundhogg"),`<b>${formatDate(after)}</b>`,`<b>${formatDate(before)}</b>`)}`;case"before":return`${prepend} ${sprintf(_x("before %s","%s is a date","groundhogg"),`<b>${formatDate(before)}</b>`)}`;case"after":return`${prepend} ${sprintf(_x("after %s","%s is a date","groundhogg"),`<b>${formatDate(after)}</b>`)}`;case"day_of":return`${prepend} ${sprintf(_x("on %s","%s is a date","groundhogg"),`<b>${formatDate(after)}</b>`)}`}};const standardActivityDateOptions=({date_range:date_range="24_hours",after:after="",before:before="",days:days=0,future:future=false})=>{return[select({id:"filter-date-range",name:"date_range"},future?futureDateRanges:pastDateRanges,date_range),input({type:"date",value:after.split(" ")[0],id:"filter-after",className:`date ${["between","after","day_of"].includes(date_range)?"":"hidden"}`,name:"after"}),input({type:"date",value:before.split(" ")[0],id:"filter-before",className:`value ${["between","before"].includes(date_range)?"":"hidden"}`,name:"before"}),input({type:"number",value:days,id:"filter-days",min:0,className:`value ${["x_days","next_x_days"].includes(date_range)?"":"hidden"}`,name:"days"})].join("")};const standardActivityDateDefaults={date_range:"any",before:"",after:"",count:1,days:0};const filterCountDefaults={count:1,count_compare:"greater_than_or_equal_to"};const activityFilterComparisons={equals:_x("Exactly","comparison","groundhogg"),less_than:_x("Less than","comparison","groundhogg"),greater_than:_x("More than","comparison","groundhogg"),less_than_or_equal_to:_x("At most","comparison","groundhogg"),greater_than_or_equal_to:_x("At least","comparison","groundhogg")};const filterCount=({count,count_compare})=>{return`
     1(function($){const{input,select,orList,andList,bold,inputRepeater}=Groundhogg.element;const{broadcastPicker,funnelPicker,tagPicker,emailPicker,linkPicker,metaValuePicker,metaPicker,userMetaPicker}=Groundhogg.pickers;const{assoc2array}=Groundhogg.functions;const{broadcasts:BroadcastsStore,emails:EmailsStore,tags:TagsStore,funnels:FunnelsStore,searches:SearchesStore}=Groundhogg.stores;const{sprintf,__,_x,_n}=wp.i18n;const{formatDate,formatDateTime,formatTime}=Groundhogg.formatting;const{Fragment,ItemPicker,Select,Input,Div,makeEl,InputRepeater}=MakeEl;const{Filters,FilterRegistry,createFilter,createGroup,FilterDisplay,createDateFilter,createPastDateFilter,createStringFilter,createNumberFilter,createTimeFilter,unsubReasons}=Groundhogg.filters;const{ComparisonsTitleGenerators,AllComparisons,StringComparisons,NumericComparisons,pastDateRanges,futureDateRanges,allDateRanges}=Groundhogg.filters.comparisons;const ContactFilterRegistry=FilterRegistry({});const uid=function(){return Date.now().toString(36)+Math.random().toString(36).substring(2)};const createFilters=(el="",filters=[],onChange=f=>{console.log(f)})=>({el:el,onChange:onChange,filters:Array.isArray(filters)?filters:[],id:uid(),init(){this.mount()},mount(){let container=document.querySelector(el);container.innerHTML="";document.querySelector(el).appendChild(ContactFilters(this.id,this.filters,this.onChange))}});const ContactFilters=(id,filters,onChange)=>Filters({id:id,filterRegistry:ContactFilterRegistry,filters:filters,onChange:onChange});const ContactFilterDisplay=filters=>FilterDisplay({filters:filters,filterRegistry:ContactFilterRegistry});const registerFilterGroup=(group,name)=>{ContactFilterRegistry.registerGroup(createGroup(group,name))};const registerFilter=(type,group="general",name="",opts={})=>{if(typeof name==="object"){let tempOpts=name;name=tempOpts.name;opts=tempOpts}const{defaults={},preload=()=>{},view=()=>"",edit=()=>"",onMount=()=>""}=opts;ContactFilterRegistry.registerFilter(createFilter(type,name,group,{display:view,preload:preload,edit:({updateFilter,...filter})=>Fragment([edit(filter)],{onCreate:el=>{setTimeout(()=>{onMount(filter,updateFilter)},50)}})},defaults))};const standardActivityDateFilterOnMount=(filter,updateFilter)=>{$("#filter-date-range, #filter-before, #filter-after, #filter-days").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()});if($el.prop("name")==="date_range"){const $before=$("#filter-before");const $after=$("#filter-after");const $days=$("#filter-days");$before.addClass("hidden");$after.addClass("hidden");$days.addClass("hidden");switch($el.val()){case"between":$before.removeClass("hidden");$after.removeClass("hidden");break;case"day_of":case"after":$after.removeClass("hidden");break;case"before":$before.removeClass("hidden");break;case"x_days":$days.removeClass("hidden");break}}})};const standardActivityDateTitle=(prepend,{date_range,before,after,days=0,future=false})=>{let ranges=future?futureDateRanges:pastDateRanges;switch(date_range){default:return`${prepend} ${ranges[date_range]?ranges[date_range].replace("X",days).toLowerCase():""}`;case"between":return`${prepend} ${sprintf(_x("between %1$s and %2$s","where %1 and %2 are dates","groundhogg"),`<b>${formatDate(after)}</b>`,`<b>${formatDate(before)}</b>`)}`;case"before":return`${prepend} ${sprintf(_x("before %s","%s is a date","groundhogg"),`<b>${formatDate(before)}</b>`)}`;case"after":return`${prepend} ${sprintf(_x("after %s","%s is a date","groundhogg"),`<b>${formatDate(after)}</b>`)}`;case"day_of":return`${prepend} ${sprintf(_x("on %s","%s is a date","groundhogg"),`<b>${formatDate(after)}</b>`)}`}};const standardActivityDateOptions=({date_range="24_hours",after="",before="",days=0,future=false})=>{return[select({id:"filter-date-range",name:"date_range"},future?futureDateRanges:pastDateRanges,date_range),input({type:"date",value:after.split(" ")[0],id:"filter-after",className:`date ${["between","after","day_of"].includes(date_range)?"":"hidden"}`,name:"after"}),input({type:"date",value:before.split(" ")[0],id:"filter-before",className:`value ${["between","before"].includes(date_range)?"":"hidden"}`,name:"before"}),input({type:"number",value:days,id:"filter-days",min:0,className:`value ${["x_days","next_x_days"].includes(date_range)?"":"hidden"}`,name:"days"})].join("")};const standardActivityDateDefaults={date_range:"any",before:"",after:"",count:1,days:0};const filterCountDefaults={count:1,count_compare:"greater_than_or_equal_to"};const activityFilterComparisons={equals:_x("Exactly","comparison","groundhogg"),less_than:_x("Less than","comparison","groundhogg"),greater_than:_x("More than","comparison","groundhogg"),less_than_or_equal_to:_x("At most","comparison","groundhogg"),greater_than_or_equal_to:_x("At least","comparison","groundhogg")};const filterCount=({count,count_compare})=>{return`
    22        <div class="space-between" style="gap: 10px">
    33            <div class="gh-input-group">
     
    88              ${__("Times")}
    99          </span>
    10         </div>`};const filterCountOnMount=updateFilter=>{$("#filter-count,#filter-count-compare").on("change",e=>{updateFilter({[e.target.name]:e.target.value})})};const filterCountComparisons={equals:v=>sprintf(_n("%s time","%s times",parseInt(v),"groundhogg"),v),less_than:v=>sprintf(_n("less than %s time","less than %s times",parseInt(v),"groundhogg"),v),less_than_or_equal_to:v=>sprintf(_n("at most %s time","at most %s times",parseInt(v),"groundhogg"),v),greater_than:v=>sprintf(_n("more than %s time","more than %s times",parseInt(v),"groundhogg"),v),greater_than_or_equal_to:v=>sprintf(_n("at least %s time","at least %s times",parseInt(v),"groundhogg"),v)};const filterCountTitle=(title,{count:count=1,count_compare:count_compare="equals"})=>{return title+" "+filterCountComparisons[count_compare](count)};const BasicTextFilter=name=>({name:name,view({compare,value}){return ComparisonsTitleGenerators[compare](`<b>${name}</b>`,`<b>"${value}"</b>`)},edit({compare,value}){return`${select({id:"filter-compare",name:"compare"},StringComparisons,compare)} ${input({id:"filter-value",name:"value",value:value})}`},onMount(filter,updateFilter){$("#filter-compare, #filter-value").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"equals",value:""}});registerFilterGroup("contact",_x("Contact","noun referring to a person in the crm","groundhogg"));registerFilterGroup("location",_x("Contact Location","contact is a noun referring to a person","groundhogg"));registerFilterGroup("user",__("User"));registerFilterGroup("activity",_x("Activity","noun referring to a persons past activities","groundhogg"));registerFilter("first_name","contact",{...BasicTextFilter(__("First Name","groundhogg"))});registerFilter("last_name","contact",{...BasicTextFilter(__("Last Name","groundhogg"))});registerFilter("email","contact",{...BasicTextFilter(__("Email Address","groundhogg"))});const phoneTypes={primary:__("Primary Phone","groundhogg"),mobile:__("Mobile Phone","groundhogg"),company:__("Company Phone","groundhogg")};registerFilter("phone","contact",{name:__("Phone Number","groundhogg"),view({phone_type:phone_type="primary",compare,value}){return ComparisonsTitleGenerators[compare](`<b>${phoneTypes[phone_type]}</b>`,`<b>"${value}"</b>`)},edit({phone_type,compare,value}){return`${select({id:"filter-phone-type",name:"phone_type"},phoneTypes,phone_type)}
     10        </div>`};const filterCountOnMount=updateFilter=>{$("#filter-count,#filter-count-compare").on("change",e=>{updateFilter({[e.target.name]:e.target.value})})};const filterCountComparisons={equals:v=>sprintf(_n("%s time","%s times",parseInt(v),"groundhogg"),v),less_than:v=>sprintf(_n("less than %s time","less than %s times",parseInt(v),"groundhogg"),v),less_than_or_equal_to:v=>sprintf(_n("at most %s time","at most %s times",parseInt(v),"groundhogg"),v),greater_than:v=>sprintf(_n("more than %s time","more than %s times",parseInt(v),"groundhogg"),v),greater_than_or_equal_to:v=>sprintf(_n("at least %s time","at least %s times",parseInt(v),"groundhogg"),v)};const filterCountTitle=(title,{count=1,count_compare="equals"})=>{return title+" "+filterCountComparisons[count_compare](count)};const BasicTextFilter=name=>({name:name,view({compare,value}){return ComparisonsTitleGenerators[compare](`<b>${name}</b>`,`<b>"${value}"</b>`)},edit({compare,value}){return`${select({id:"filter-compare",name:"compare"},StringComparisons,compare)} ${input({id:"filter-value",name:"value",value:value})}`},onMount(filter,updateFilter){$("#filter-compare, #filter-value").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"equals",value:""}});registerFilterGroup("contact",_x("Contact","noun referring to a person in the crm","groundhogg"));registerFilterGroup("location",_x("Contact Location","contact is a noun referring to a person","groundhogg"));registerFilterGroup("user",__("User"));registerFilterGroup("activity",_x("Activity","noun referring to a persons past activities","groundhogg"));registerFilter("first_name","contact",{...BasicTextFilter(__("First Name","groundhogg"))});registerFilter("last_name","contact",{...BasicTextFilter(__("Last Name","groundhogg"))});registerFilter("email","contact",{...BasicTextFilter(__("Email Address","groundhogg"))});const phoneTypes={primary:__("Primary Phone","groundhogg"),mobile:__("Mobile Phone","groundhogg"),company:__("Company Phone","groundhogg")};registerFilter("phone","contact",{name:__("Phone Number","groundhogg"),view({phone_type="primary",compare,value}){return ComparisonsTitleGenerators[compare](`<b>${phoneTypes[phone_type]}</b>`,`<b>"${value}"</b>`)},edit({phone_type,compare,value}){return`${select({id:"filter-phone-type",name:"phone_type"},phoneTypes,phone_type)}
    1111      ${select({id:"filter-compare",name:"compare"},StringComparisons,compare)} ${input({id:"filter-value",name:"value",value:value})}`},onMount(filter,updateFilter){$("#filter-phone-type, #filter-compare, #filter-value").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{phone_type:"primary",compare:"equals",value:""}});ContactFilterRegistry.registerFilter(createDateFilter("birthday",__("Birthday","groundhogg"),"contact"));ContactFilterRegistry.registerFilter(createNumberFilter("age",__("Age","groundhogg"),"contact"));ContactFilterRegistry.registerFilter(createPastDateFilter("date_created",__("Date Created","groundhogg"),"contact"));const{optin_status,owners,countries,roles}=Groundhogg.filters;registerFilter("optin_status","contact",__("Opt-in Status","groundhogg"),{view({compare,value}){const func=compare==="in"?orList:andList;return ComparisonsTitleGenerators[compare](`<b>${__("Opt-in Status","groundhogg")}</b>`,func(value.map(v=>`<b>${optin_status[v]}</b>`)))},edit({compare,value}){return`
    1212          ${select({id:"filter-compare",name:"compare",class:""},{in:_x("Is one of","comparison, groundhogg"),not_in:_x("Is not one of","comparison","groundhogg")},compare)}
    1313          ${select({id:"filter-value",name:"value",class:"gh-select2",multiple:true},Object.keys(optin_status).map(k=>({value:k,text:optin_status[k]})),value)} `},onMount(filter,updateFilter){$("#filter-value").select2();$("#filter-value, #filter-compare").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"in",value:[]}});registerFilter("is_marketable","contact",__("Marketable","groundhogg"),{view({marketable}){return marketable==="yes"?__("Is marketable","groundhogg"):__("Is not marketable","groundhogg")},edit({marketable}){return`
    14           ${select({id:"filter-marketable",name:"marketable"},{yes:_x("Yes","comparison, groundhogg"),no:_x("No","comparison","groundhogg")},marketable)}`},onMount(filter,updateFilter){$("#filter-marketable").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{marketable:"yes"}});const userDisplay=user=>{return`${user.data.display_name} (${user.data.user_email})`};registerFilter("owner","contact",__("Owner","groundhogg"),{view({compare,value:value=[]}){if(!value.length){throw new Error("At least 1 owner must be selected.")}const ownerName=ID=>{let user=owners.find(owner=>owner.ID==ID);if(!user){throw new Error(`Owner with ID ${ID} does not exist`)}return userDisplay(user)};const func=compare==="in"?orList:andList;return ComparisonsTitleGenerators[compare](`<b>${__("Contact Owner","groundhogg")}</b>`,func(value.map(v=>`<b>${ownerName(v)}</b>`)))},edit({compare,value}){return`
     14          ${select({id:"filter-marketable",name:"marketable"},{yes:_x("Yes","comparison, groundhogg"),no:_x("No","comparison","groundhogg")},marketable)}`},onMount(filter,updateFilter){$("#filter-marketable").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{marketable:"yes"}});const userDisplay=user=>{return`${user.data.display_name} (${user.data.user_email})`};registerFilter("owner","contact",__("Owner","groundhogg"),{view({compare,value=[]}){if(!value.length){throw new Error("At least 1 owner must be selected.")}const ownerName=ID=>{let user=owners.find(owner=>owner.ID==ID);if(!user){throw new Error(`Owner with ID ${ID} does not exist`)}return userDisplay(user)};const func=compare==="in"?orList:andList;return ComparisonsTitleGenerators[compare](`<b>${__("Contact Owner","groundhogg")}</b>`,func(value.map(v=>`<b>${ownerName(v)}</b>`)))},edit({compare,value}){return`
    1515          ${select({id:"filter-compare",name:"compare"},{in:_x("Is one of","comparison, groundhogg"),not_in:_x("Is not one of","comparison","groundhogg")},compare)}
    1616
    17           ${select({id:"filter-value",name:"value",multiple:true},owners.map(u=>({value:u.ID,text:userDisplay(u)})),value.map(id=>parseInt(id)))} `},onMount(filter,updateFilter){$("#filter-value").select2();$("#filter-value, #filter-compare").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"in",value:[]}});registerFilter("tags","contact",_x("Tags","noun referring to contact segments","groundhogg"),{view({tags:tags=[],compare,compare2}){if(!tags){return"tags"}tags=tags.map(t=>{let tag=TagsStore.get(parseInt(t));if(!tag){throw new Error(`Tag of ID ${t} does not exist`)}return tag});const tagNames=tags.map(t=>`<b>${t.data.tag_name}</b>`);const func=compare2==="any"?orList:andList;return ComparisonsTitleGenerators[compare](`<b>${_x("Tags","noun referring to contact segments","groundhogg")}</b>`,func(tagNames))},edit({tags,compare,compare2}){tags=tags.map(t=>TagsStore.get(parseInt(t))).filter(Boolean);return`${select({id:"filter-compare",name:"compare"},{includes:_x("Includes","comparison","groundhogg"),excludes:_x("Excludes","comparison","groundhogg")},compare)}
     17          ${select({id:"filter-value",name:"value",multiple:true},owners.map(u=>({value:u.ID,text:userDisplay(u)})),value.map(id=>parseInt(id)))} `},onMount(filter,updateFilter){$("#filter-value").select2();$("#filter-value, #filter-compare").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"in",value:[]}});registerFilter("tags","contact",_x("Tags","noun referring to contact segments","groundhogg"),{view({tags=[],compare,compare2}){if(!tags){return"tags"}tags=tags.map(t=>{let tag=TagsStore.get(parseInt(t));if(!tag){throw new Error(`Tag of ID ${t} does not exist`)}return tag});const tagNames=tags.map(t=>`<b>${t.data.tag_name}</b>`);const func=compare2==="any"?orList:andList;return ComparisonsTitleGenerators[compare](`<b>${_x("Tags","noun referring to contact segments","groundhogg")}</b>`,func(tagNames))},edit({tags,compare,compare2}){tags=tags.map(t=>TagsStore.get(parseInt(t))).filter(Boolean);return`${select({id:"filter-compare",name:"compare"},{includes:_x("Includes","comparison","groundhogg"),excludes:_x("Excludes","comparison","groundhogg")},compare)}
    1818
    1919        ${select({id:"filter-compare2",name:"compare2"},{any:__("Any","groundhogg"),all:__("All","groundhogg")},compare2)}
    2020
    2121        ${select({id:"filter-tags",name:"tags",className:"tag-picker",multiple:true},tags.map(t=>({value:t.ID,text:t.data.tag_name})),tags.map(t=>t.ID))}`},onMount(filter,updateFilter){tagPicker("#filter-tags",true,items=>{TagsStore.itemsFetched(items)},{tags:false}).on("change",e=>{updateFilter({tags:$(e.target).val()})});$("#filter-compare, #filter-compare2").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"includes",compare2:"any",tags:[]},preload:({tags})=>{if(!TagsStore.hasItems(tags)){return TagsStore.fetchItems({tag_id:tags})}}});registerFilter("meta","contact",__("Custom meta","groundhogg"),{view({meta,compare,value}){return ComparisonsTitleGenerators[compare](`<b>${meta}</b>`,`<b>"${value}"</b>`)},edit({meta,compare,value},filterGroupIndex,filterIndex){return[input({id:"filter-meta",name:"meta",className:"meta-picker",dataGroup:filterIndex,dataKey:filterIndex,value:meta}),select({id:"filter-compare",name:"compare",dataGroup:filterIndex,dataKey:filterIndex},AllComparisons,compare),["empty","not_empty"].includes(compare)?"":input({id:"filter-value",name:"value",dataGroup:filterIndex,dataKey:filterIndex,value:value})].join("")},onMount(filter,updateFilter){metaPicker("#filter-meta");$("#filter-compare, #filter-value, #filter-meta").on("change blur",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()},true)})},defaults:{meta:"",compare:"equals",value:""}});registerFilter("contact_id","contact",__("Contact ID","groundhogg"),{view({compare,value}){return ComparisonsTitleGenerators[compare](`<b>${__("Contact ID")}</b>`,`<b>${value}</b>`)},edit({compare,value}){return`
    22           ${select({id:"filter-compare",name:"compare"},NumericComparisons,compare)} ${input({id:"filter-value",name:"value",type:"number",step:"0.01",value:value})}`},onMount(filter,updateFilter){$("#filter-compare, #filter-value").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"equals",value:""}});registerFilter("is_user","user",__("Has User Account","groundhogg"),{view(){return __("Has a user account","groundhogg")},edit(){return""},onMount(filter,updateFilter){},defaults:{}});registerFilter("user_role_is","user",__("User Role","groundhogg"),{view({role:role="subscriber"}){return sprintf(__("User role is %s","groundhogg"),bold(role?roles[role].name:""))},edit({role}){return`${select({id:"filter-role",name:"role"},Object.keys(roles).map(r=>({text:roles[r].name,value:r})),role)}`},onMount(filter,updateFilter){$("#filter-role").select2({placeholder:__("Select a role","groundhogg")}).on("change",function(e){const $el=$(this);updateFilter({role:$el.val()})})},defaults:{role:"subscriber"}});registerFilter("user_meta","user",__("User Meta","groundhogg"),{view({meta,compare,value}){return ComparisonsTitleGenerators[compare](`<b>${meta}</b>`,`<b>"${value}"</b>`)},edit({meta,compare,value},filterGroupIndex,filterIndex){return`
     22          ${select({id:"filter-compare",name:"compare"},NumericComparisons,compare)} ${input({id:"filter-value",name:"value",type:"number",step:"0.01",value:value})}`},onMount(filter,updateFilter){$("#filter-compare, #filter-value").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{compare:"equals",value:""}});registerFilter("is_user","user",__("Has User Account","groundhogg"),{view(){return __("Has a user account","groundhogg")},edit(){return""},onMount(filter,updateFilter){},defaults:{}});registerFilter("user_role_is","user",__("User Role","groundhogg"),{view({role="subscriber"}){return sprintf(__("User role is %s","groundhogg"),bold(role?roles[role].name:""))},edit({role}){return`${select({id:"filter-role",name:"role"},Object.keys(roles).map(r=>({text:roles[r].name,value:r})),role)}`},onMount(filter,updateFilter){$("#filter-role").select2({placeholder:__("Select a role","groundhogg")}).on("change",function(e){const $el=$(this);updateFilter({role:$el.val()})})},defaults:{role:"subscriber"}});registerFilter("user_meta","user",__("User Meta","groundhogg"),{view({meta,compare,value}){return ComparisonsTitleGenerators[compare](`<b>${meta}</b>`,`<b>"${value}"</b>`)},edit({meta,compare,value},filterGroupIndex,filterIndex){return`
    2323          ${input({id:"filter-meta",name:"meta",className:"meta-picker",dataGroup:filterIndex,dataKey:filterIndex,value:meta})}
    2424          ${select({id:"filter-compare",name:"compare",dataGroup:filterIndex,dataKey:filterIndex},AllComparisons,compare)} ${input({id:"filter-value",name:"value",dataGroup:filterIndex,dataKey:filterIndex,value:value})}`},onMount(filter,updateFilter){userMetaPicker("#filter-meta");$("#filter-compare, #filter-value, #filter-meta").on("change blur",function(e){const $el=$(this);const{compare}=updateFilter({[$el.prop("name")]:$el.val()})})},defaults:{meta:"",compare:"equals",value:""}});registerFilter("user_id","user",__("User ID","groundhogg"),{view({compare,value}){return ComparisonsTitleGenerators[compare](`<b>${__("User ID")}</b>`,`<b>${value}</b>`)},edit({compare,value}){return`
     
    2626          ${select({id:"filter-country",name:"country"},countries,country)}`},onMount(filter,updateFilter){$("#filter-country").select2().on("change",function(e){const $el=$(this);updateFilter({country:$el.val()})})},defaults:{country:""}});registerFilter("region","location",__("State/Province","groundhogg"),{view({region}){return sprintf(__("State/Province is %s","groundhogg"),bold(region))},edit({region}){return`
    2727          ${input({id:"filter-region",name:"region",value:region,autocomplete:"off",placeholder:__("Start typing to select a region","groundhogg")})}`},onMount(filter,updateFilter){metaValuePicker("#filter-region","region").on("change blur",function(e){updateFilter({region:$(e.target).val()})})},defaults:{region:""}});registerFilter("city","location",__("City","groundhogg"),{view({city}){return sprintf(__("City is %s","groundhogg"),bold(city))},edit({city}){return`
    28           ${input({id:"filter-city",name:"city",value:city,autocomplete:"off",placeholder:__("Start typing to select a city","groundhogg")})}`},onMount(filter,updateFilter){metaValuePicker("#filter-city","city").on("change blur",function(e){updateFilter({city:$(e.target).val()})})},defaults:{city:""}});registerFilter("street_address_1","location",__("Line 1","groundhogg"),{...BasicTextFilter(__("Street Address 1","groundhogg"))});registerFilter("street_address_2","location",__("Line 2","groundhogg"),{...BasicTextFilter(__("Street Address 2","groundhogg"))});registerFilter("zip_code","location",__("Zip/Postal Code","groundhogg"),{...BasicTextFilter(__("Zip/Postal Code","groundhogg"))});registerFilter("locale","location",__("Locale","groundhogg"),{view({locales:locales=[]}){if(!locales.length){throw new Error("Select a locale")}let dropdown=Div({},GroundhoggLocalDropdown).firstElementChild;locales=locales.map(locale=>bold(dropdown.querySelector(`option[value="${locale}"]`).innerHTML));return sprintf("%s is %s",bold(__("Locale")),orList(locales))},edit({locales:locales=[]}){let dropdown=Div({},GroundhoggLocalDropdown).firstElementChild;dropdown.multiple=true;locales.forEach(locale=>{dropdown.querySelector(`option[value="${locale}"]`).selected=true});return dropdown},onMount(filter,updateFilter){$("#filter-locale").select2({multiple:true}).on("change",function(e){const $el=$(this);updateFilter({locales:$el.val()})})},defaults:{locales:["en_US"]}});registerFilter("email_received","activity",__("Email Received","groundhogg"),{view({email_id,...rest}){const emailName=email_id?EmailsStore.get(email_id).data.title:"any email";let prefix=sprintf(_x("Received %s","%s is an email","groundhogg"),`<b>${emailName}</b>`);prefix=filterCountTitle(prefix,rest);return standardActivityDateTitle(prefix,rest)},edit({email_id,...rest}){const pickerOptions=email_id?{[email_id]:EmailsStore.get(email_id).data.title}:{};return`
     28          ${input({id:"filter-city",name:"city",value:city,autocomplete:"off",placeholder:__("Start typing to select a city","groundhogg")})}`},onMount(filter,updateFilter){metaValuePicker("#filter-city","city").on("change blur",function(e){updateFilter({city:$(e.target).val()})})},defaults:{city:""}});registerFilter("street_address_1","location",__("Line 1","groundhogg"),{...BasicTextFilter(__("Street Address 1","groundhogg"))});registerFilter("street_address_2","location",__("Line 2","groundhogg"),{...BasicTextFilter(__("Street Address 2","groundhogg"))});registerFilter("zip_code","location",__("Zip/Postal Code","groundhogg"),{...BasicTextFilter(__("Zip/Postal Code","groundhogg"))});registerFilter("locale","location",__("Locale","groundhogg"),{view({locales=[]}){if(!locales.length){throw new Error("Select a locale")}let dropdown=Div({},GroundhoggLocalDropdown).firstElementChild;locales=locales.map(locale=>bold(dropdown.querySelector(`option[value="${locale}"]`).innerHTML));return sprintf("%s is %s",bold(__("Locale")),orList(locales))},edit({locales=[]}){let dropdown=Div({},GroundhoggLocalDropdown).firstElementChild;dropdown.multiple=true;locales.forEach(locale=>{dropdown.querySelector(`option[value="${locale}"]`).selected=true});return dropdown},onMount(filter,updateFilter){$("#filter-locale").select2({multiple:true}).on("change",function(e){const $el=$(this);updateFilter({locales:$el.val()})})},defaults:{locales:["en_US"]}});registerFilter("email_received","activity",__("Email Received","groundhogg"),{view({email_id,...rest}){const emailName=email_id?EmailsStore.get(email_id).data.title:"any email";let prefix=sprintf(_x("Received %s","%s is an email","groundhogg"),`<b>${emailName}</b>`);prefix=filterCountTitle(prefix,rest);return standardActivityDateTitle(prefix,rest)},edit({email_id,...rest}){const pickerOptions=email_id?{[email_id]:EmailsStore.get(email_id).data.title}:{};return`
    2929            ${select({id:"filter-email",name:"email_id"},pickerOptions,email_id)}
    3030
     
    3636          ${filterCount(rest)}
    3737
    38           ${standardActivityDateOptions(rest)}`},onMount(filter,updateFilter){emailPicker("#filter-email",false,items=>{EmailsStore.itemsFetched(items)},{},{placeholder:__("Please select an email or leave blank for any email","groundhogg")}).on("change",e=>{updateFilter({email_id:parseInt(e.target.value)})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults,email_id:0},preload:({email_id})=>{if(email_id){return EmailsStore.maybeFetchItem(email_id)}}});registerFilter("email_link_clicked","activity",__("Email Link Clicked","groundhogg"),{view({email_id,link:link="",...rest}){const emailName=email_id?EmailsStore.get(email_id).data.title:"any email";const maybeTruncateLink=link=>{return link.length>50?`${link.substring(0,47)}...`:link};let prepend=sprintf(link?__("Clicked %1$s in %2$s","groundhogg"):__("Clicked any link in %2$s","groundhogg"),`<b class="link" title="${link}">${maybeTruncateLink(link)}</b>`,`<b>${emailName}</b>`);prepend=filterCountTitle(prepend,rest);return standardActivityDateTitle(prepend,rest)},edit({email_id,link,...rest}){const pickerOptions=email_id?{[email_id]:EmailsStore.get(email_id).data.title}:{};return`
     38          ${standardActivityDateOptions(rest)}`},onMount(filter,updateFilter){emailPicker("#filter-email",false,items=>{EmailsStore.itemsFetched(items)},{},{placeholder:__("Please select an email or leave blank for any email","groundhogg")}).on("change",e=>{updateFilter({email_id:parseInt(e.target.value)})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults,email_id:0},preload:({email_id})=>{if(email_id){return EmailsStore.maybeFetchItem(email_id)}}});registerFilter("email_link_clicked","activity",__("Email Link Clicked","groundhogg"),{view({email_id,link="",...rest}){const emailName=email_id?EmailsStore.get(email_id).data.title:"any email";const maybeTruncateLink=link=>{return link.length>50?`${link.substring(0,47)}...`:link};let prepend=sprintf(link?__("Clicked %1$s in %2$s","groundhogg"):__("Clicked any link in %2$s","groundhogg"),`<b class="link" title="${link}">${maybeTruncateLink(link)}</b>`,`<b>${emailName}</b>`);prepend=filterCountTitle(prepend,rest);return standardActivityDateTitle(prepend,rest)},edit({email_id,link,...rest}){const pickerOptions=email_id?{[email_id]:EmailsStore.get(email_id).data.title}:{};return`
    3939            ${select({id:"filter-email",name:"email_id"},pickerOptions,email_id)}
    4040
     
    4343            ${filterCount(rest)}
    4444
    45             ${standardActivityDateOptions(rest)}`},onMount(filter,updateFilter){emailPicker("#filter-email",false,items=>{EmailsStore.itemsFetched(items)},{},{placeholder:__("Please select an email or leave blank for any email","groundhogg")}).on("change",e=>{updateFilter({email_id:parseInt(e.target.value)})});linkPicker("#filter-link").on("change input blur",({target})=>{updateFilter({link:target.value})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults,link:"",email_id:0},preload:({email_id})=>{if(email_id){return EmailsStore.maybeFetchItem(email_id)}}});registerFilter("confirmed_email","activity",__("Confirmed Email Address","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Confirmed Email Address","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});ContactFilterRegistry.registerFilter(createPastDateFilter("unsubscribed",__("Unsubscribed","groundhogg"),"activity",{edit:({reasons:reasons=[],updateFilter})=>Fragment([ItemPicker({id:"unsub-reasons",placeholder:__("Search","groundhogg"),noneSelected:__("Any reason","groundhogg"),fetchOptions:async s=>assoc2array(unsubReasons),selected:reasons.map(reason=>({id:reason,text:unsubReasons[reason]??reason})),onChange:items=>{let reasons=items.map(({id})=>id);console.log(reasons);updateFilter({reasons:reasons})}})]),display:({reasons:reasons=[]})=>sprintf("Unsubscribed %s",orList(reasons.map(r=>bold(unsubReasons[r]??r))))}));registerFilter("optin_status_changed","activity",__("Opt-in Status Changed","groundhogg"),{view({value,...filter}){return standardActivityDateTitle(sprintf("<b>Opt-in status</b> changed to %s",orList(value.map(v=>`<b>${optin_status[v]}</b>`))),filter)},edit({value,...filter}){return[select({id:"filter-value",name:"value",class:"gh-select2",multiple:true},Object.keys(optin_status).map(k=>({value:k,text:optin_status[k]})),value),standardActivityDateOptions(filter)].join("")},onMount(filter,updateFilter){$("#filter-value").select2();$("#filter-value").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})});standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{value:[],...standardActivityDateDefaults}});registerFilter("page_visited","activity",__("Page Visited","groundhogg"),{view({link,...rest}){let prefix;if(link){const url=new URL(link);prefix=sprintf(__("Visited %s","groundhogg"),bold(url.pathname))}else{prefix=__("Visited <b>any page</b>","groundhogg")}prefix=filterCountTitle(prefix,rest);return standardActivityDateTitle(prefix,rest)},edit({link,...rest}){return`
     45            ${standardActivityDateOptions(rest)}`},onMount(filter,updateFilter){emailPicker("#filter-email",false,items=>{EmailsStore.itemsFetched(items)},{},{placeholder:__("Please select an email or leave blank for any email","groundhogg")}).on("change",e=>{updateFilter({email_id:parseInt(e.target.value)})});linkPicker("#filter-link").on("change input blur",({target})=>{updateFilter({link:target.value})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults,link:"",email_id:0},preload:({email_id})=>{if(email_id){return EmailsStore.maybeFetchItem(email_id)}}});registerFilter("confirmed_email","activity",__("Confirmed Email Address","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Confirmed Email Address","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});ContactFilterRegistry.registerFilter(createPastDateFilter("unsubscribed",__("Unsubscribed","groundhogg"),"activity",{edit:({reasons=[],updateFilter})=>Fragment([ItemPicker({id:"unsub-reasons",placeholder:__("Search","groundhogg"),noneSelected:__("Any reason","groundhogg"),fetchOptions:async s=>assoc2array(unsubReasons),selected:reasons.map(reason=>({id:reason,text:unsubReasons[reason]??reason})),onChange:items=>{let reasons=items.map(({id})=>id);console.log(reasons);updateFilter({reasons:reasons})}})]),display:({reasons=[]})=>sprintf("Unsubscribed %s",orList(reasons.map(r=>bold(unsubReasons[r]??r))))}));registerFilter("optin_status_changed","activity",__("Opt-in Status Changed","groundhogg"),{view({value,...filter}){return standardActivityDateTitle(sprintf("<b>Opt-in status</b> changed to %s",orList(value.map(v=>`<b>${optin_status[v]}</b>`))),filter)},edit({value,...filter}){return[select({id:"filter-value",name:"value",class:"gh-select2",multiple:true},Object.keys(optin_status).map(k=>({value:k,text:optin_status[k]})),value),standardActivityDateOptions(filter)].join("")},onMount(filter,updateFilter){$("#filter-value").select2();$("#filter-value").on("change",function(e){const $el=$(this);updateFilter({[$el.prop("name")]:$el.val()})});standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{value:[],...standardActivityDateDefaults}});registerFilter("page_visited","activity",__("Page Visited","groundhogg"),{view({link,...rest}){let prefix;if(link){const url=new URL(link);prefix=sprintf(__("Visited %s","groundhogg"),bold(url.pathname))}else{prefix=__("Visited <b>any page</b>","groundhogg")}prefix=filterCountTitle(prefix,rest);return standardActivityDateTitle(prefix,rest)},edit({link,...rest}){return`
    4646
    4747          ${input({id:"filter-link",name:"link",autocomplete:"off",value:link,placeholder:__("Start typing to select a link or leave blank for any link","groundhogg")})}
     
    4949          ${filterCount(rest)}
    5050
    51           ${standardActivityDateOptions(rest)}`},onMount(filter,updateFilter){linkPicker("#filter-link").on("change input blur",({target})=>{updateFilter({link:target.value})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults,link:""}});registerFilter("logged_in","activity",__("Logged In","groundhogg"),{view(filter){let prefix=filterCountTitle(`<b>${__("Logged in","groundhogg")}</b>`,filter);return standardActivityDateTitle(prefix,filter)},edit(filter){return filterCount(filter)+standardActivityDateOptions(filter)},onMount(filter,updateFilter){filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults}});registerFilter("logged_out","activity",__("Logged Out","groundhogg"),{view(filter){return standardActivityDateTitle(filterCountTitle(`<b>${__("Logged out","groundhogg")}</b>`,filter),filter)},edit(filter){return filterCount(filter)+standardActivityDateOptions(filter)},onMount(filter,updateFilter){filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...filterCountDefaults,...standardActivityDateDefaults}});registerFilter("not_logged_in","activity",__("Has Not Logged In","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Has not logged in","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});registerFilter("was_active","activity",__("Was Active","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Was active","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});registerFilter("was_not_active","activity",__("Was Inactive","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Was inactive","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});registerFilterGroup("funnels",_x("Flows","noun meaning automation","groundhogg"));registerFilter("funnel_history","funnels",__("Flow History","groundhogg"),{view({status:status="complete",funnel_id:funnel_id=0,step_id:step_id=0,date_range:date_range="any",before,after,...rest}){let prepend;if(funnel_id){const funnel=FunnelsStore.get(funnel_id);const step=funnel.steps.find(s=>s.ID===step_id);prepend=status==="complete"?sprintf(step?__("Completed %2$s in %1$s","groundhogg"):__("Completed any step in %1$s","groundhogg"),`<b>${funnel.data.title}</b>`,step?`<b>${step.data.step_title}</b>`:""):sprintf(step?__("Will complete %2$s in %1$s","groundhogg"):__("Will complete any step in %1$s","groundhogg"),`<b>${funnel.data.title}</b>`,step?`<b>${step.data.step_title}</b>`:"");if(status==="waiting"){return prepend}}else{prepend=__("Completed any step in any flow","groundhogg")}return standardActivityDateTitle(prepend,{date_range:date_range,before:before,after:after,...rest})},edit({funnel_id,step_id,date_range,before,after,...rest}){return`
     51          ${standardActivityDateOptions(rest)}`},onMount(filter,updateFilter){linkPicker("#filter-link").on("change input blur",({target})=>{updateFilter({link:target.value})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults,link:""}});registerFilter("logged_in","activity",__("Logged In","groundhogg"),{view(filter){let prefix=filterCountTitle(`<b>${__("Logged in","groundhogg")}</b>`,filter);return standardActivityDateTitle(prefix,filter)},edit(filter){return filterCount(filter)+standardActivityDateOptions(filter)},onMount(filter,updateFilter){filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults,...filterCountDefaults}});registerFilter("logged_out","activity",__("Logged Out","groundhogg"),{view(filter){return standardActivityDateTitle(filterCountTitle(`<b>${__("Logged out","groundhogg")}</b>`,filter),filter)},edit(filter){return filterCount(filter)+standardActivityDateOptions(filter)},onMount(filter,updateFilter){filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...filterCountDefaults,...standardActivityDateDefaults}});registerFilter("not_logged_in","activity",__("Has Not Logged In","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Has not logged in","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});registerFilter("was_active","activity",__("Was Active","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Was active","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});registerFilter("was_not_active","activity",__("Was Inactive","groundhogg"),{view(filter){return standardActivityDateTitle(`<b>${__("Was inactive","groundhogg")}</b>`,filter)},edit(filter){return standardActivityDateOptions(filter)},onMount(filter,updateFilter){standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...standardActivityDateDefaults}});registerFilterGroup("funnels",_x("Flows","noun meaning automation","groundhogg"));registerFilter("funnel_history","funnels",__("Flow History","groundhogg"),{view({status="complete",funnel_id=0,step_id=0,date_range="any",before,after,...rest}){let prepend;if(funnel_id){const funnel=FunnelsStore.get(funnel_id);const step=funnel.steps.find(s=>s.ID===step_id);prepend=status==="complete"?sprintf(step?__("Completed %2$s in %1$s","groundhogg"):__("Completed any step in %1$s","groundhogg"),`<b>${funnel.data.title}</b>`,step?`<b>${step.data.step_title}</b>`:""):sprintf(step?__("Will complete %2$s in %1$s","groundhogg"):__("Will complete any step in %1$s","groundhogg"),`<b>${funnel.data.title}</b>`,step?`<b>${step.data.step_title}</b>`:"");if(status==="waiting"){return prepend}}else{prepend=__("Completed any step in any flow","groundhogg")}return standardActivityDateTitle(prepend,{date_range:date_range,before:before,after:after,...rest})},edit({funnel_id,step_id,date_range,before,after,...rest}){return`
    5252      ${select({id:"filter-funnel",name:"funnel_id"},FunnelsStore.getItems().map(f=>({value:f.ID,text:f.data.title})),funnel_id)}
    5353      ${select({id:"filter-step",name:"step_id"},funnel_id?FunnelsStore.get(funnel_id).steps.map(s=>({value:s.ID,text:s.data.step_title})):[],step_id)}
    54       ${standardActivityDateOptions({date_range:date_range,before:before,after:after,...rest})}`},onMount(filter,updateFilter){funnelPicker("#filter-funnel",false,items=>{FunnelsStore.itemsFetched(items)},{},{placeholder:__("Select a flow","groundhogg")}).on("select2:select",({target})=>{updateFilter({funnel_id:parseInt($(target).val()),step_id:0},true)});$("#filter-step").select2({placeholder:__("Select a step or leave empty for any step","groundhogg")}).on("select2:select",({target})=>{updateFilter({step_id:parseInt($(target).val())})});standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{funnel_id:0,step_id:0,status:"complete",...standardActivityDateDefaults},preload:({funnel_id})=>{if(funnel_id){return FunnelsStore.maybeFetchItem(funnel_id)}}});registerFilterGroup("broadcast",_x("Broadcast","noun meaning email blast","groundhogg"));registerFilter("broadcast_received","broadcast",__("Received Broadcast","groundhogg"),{view({broadcast_id,status:status="complete"}){if(!broadcast_id){return __("Received any broadcast","groundhogg")}const broadcast=BroadcastsStore.get(broadcast_id);return status==="complete"?sprintf(broadcast?__("Received %1$s on %2$s","groundhogg"):__("Will receive a broadcast","groundhogg"),`<b>${broadcast.object.data.title}</b>`,`<b>${formatDateTime(broadcast.data.send_time*1e3)}</b>`):sprintf(broadcast?__("Will receive %1$s on %2$s","groundhogg"):__("Received a broadcast","groundhogg"),`<b>${broadcast.object.data.title}</b>`,`<b>${formatDateTime(broadcast.data.send_time*1e3)}</b>`)},edit({broadcast_id}){return select({id:"filter-broadcast",name:"broadcast_id"},BroadcastsStore.getItems().map(b=>({value:b.ID,text:`${b.object.data.title} (${b.date_sent_pretty})`})),broadcast_id)},onMount(filter,updateFilter){broadcastPicker("#filter-broadcast",false,items=>{BroadcastsStore.itemsFetched(items)},{},{placeholder:__("Select a broadcast","groundhogg")}).on("select2:select",({target})=>{updateFilter({broadcast_id:parseInt($(target).val())})})},defaults:{broadcast_id:0,status:"complete"},preload:({broadcast_id})=>{if(broadcast_id){return BroadcastsStore.maybeFetchItem(broadcast_id)}}});registerFilter("broadcast_opened","broadcast",__("Opened Broadcast","groundhogg"),{view({broadcast_id}){if(!broadcast_id){return __("Opened any broadcast","groundhogg")}const broadcast=BroadcastsStore.get(broadcast_id);return sprintf(broadcast?__("Opened %1$s after %2$s","groundhogg"):__("Will receive a broadcast","groundhogg"),`<b>${broadcast.object.data.title}</b>`,`<b>${formatDateTime(broadcast.data.send_time*1e3)}</b>`)},edit({broadcast_id}){return select({id:"filter-broadcast",name:"broadcast_id"},BroadcastsStore.getItems().map(b=>({value:b.ID,text:`${b.object.data.title} (${b.date_sent_pretty})`})),broadcast_id)},onMount(filter,updateFilter){broadcastPicker("#filter-broadcast",false,items=>{BroadcastsStore.itemsFetched(items)},{},{placeholder:__("Select a broadcast","groundhogg")}).on("select2:select",({target})=>{updateFilter({broadcast_id:parseInt($(target).val())})})},defaults:{broadcast_id:0},preload:({broadcast_id})=>{if(broadcast_id){return BroadcastsStore.maybeFetchItem(broadcast_id)}}});registerFilter("broadcast_link_clicked","broadcast",__("Broadcast Link Clicked","groundhogg"),{view({broadcast_id,link}){if(!broadcast_id&&!link){return __("Clicked any link in any broadcast","groundhogg")}if(!broadcast_id&&link){return sprintf(__("Clicked %s in any broadcast","groundhogg"),bold(link))}const broadcast=BroadcastsStore.get(broadcast_id);if(broadcast_id&&!link){return sprintf(__("Clicked any link in %1$s after %2$s","groundhogg"),bold(broadcast.object.data.title),bold(formatDateTime(broadcast.data.send_time*1e3)))}return sprintf(__("Clicked %1$s in %2$s after %3$s","groundhogg"),bold(link),bold(broadcast.object.data.title),bold(formatDateTime(broadcast.data.send_time*1e3)))},edit({broadcast_id,link}){return`
     54      ${standardActivityDateOptions({date_range:date_range,before:before,after:after,...rest})}`},onMount(filter,updateFilter){funnelPicker("#filter-funnel",false,items=>{FunnelsStore.itemsFetched(items)},{},{placeholder:__("Select a flow","groundhogg")}).on("select2:select",({target})=>{updateFilter({funnel_id:parseInt($(target).val()),step_id:0},true)});$("#filter-step").select2({placeholder:__("Select a step or leave empty for any step","groundhogg")}).on("select2:select",({target})=>{updateFilter({step_id:parseInt($(target).val())})});standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{funnel_id:0,step_id:0,status:"complete",...standardActivityDateDefaults},preload:({funnel_id})=>{if(funnel_id){return FunnelsStore.maybeFetchItem(funnel_id)}}});registerFilterGroup("broadcast",_x("Broadcast","noun meaning email blast","groundhogg"));registerFilter("broadcast_received","broadcast",__("Received Broadcast","groundhogg"),{view({broadcast_id,status="complete"}){if(!broadcast_id){return __("Received any broadcast","groundhogg")}const broadcast=BroadcastsStore.get(broadcast_id);return status==="complete"?sprintf(broadcast?__("Received %1$s on %2$s","groundhogg"):__("Will receive a broadcast","groundhogg"),`<b>${broadcast.object.data.title}</b>`,`<b>${formatDateTime(broadcast.data.send_time*1e3)}</b>`):sprintf(broadcast?__("Will receive %1$s on %2$s","groundhogg"):__("Received a broadcast","groundhogg"),`<b>${broadcast.object.data.title}</b>`,`<b>${formatDateTime(broadcast.data.send_time*1e3)}</b>`)},edit({broadcast_id}){return select({id:"filter-broadcast",name:"broadcast_id"},BroadcastsStore.getItems().map(b=>({value:b.ID,text:`${b.object.data.title} (${b.date_sent_pretty})`})),broadcast_id)},onMount(filter,updateFilter){broadcastPicker("#filter-broadcast",false,items=>{BroadcastsStore.itemsFetched(items)},{},{placeholder:__("Select a broadcast","groundhogg")}).on("select2:select",({target})=>{updateFilter({broadcast_id:parseInt($(target).val())})})},defaults:{broadcast_id:0,status:"complete"},preload:({broadcast_id})=>{if(broadcast_id){return BroadcastsStore.maybeFetchItem(broadcast_id)}}});registerFilter("broadcast_opened","broadcast",__("Opened Broadcast","groundhogg"),{view({broadcast_id}){if(!broadcast_id){return __("Opened any broadcast","groundhogg")}const broadcast=BroadcastsStore.get(broadcast_id);return sprintf(broadcast?__("Opened %1$s after %2$s","groundhogg"):__("Will receive a broadcast","groundhogg"),`<b>${broadcast.object.data.title}</b>`,`<b>${formatDateTime(broadcast.data.send_time*1e3)}</b>`)},edit({broadcast_id}){return select({id:"filter-broadcast",name:"broadcast_id"},BroadcastsStore.getItems().map(b=>({value:b.ID,text:`${b.object.data.title} (${b.date_sent_pretty})`})),broadcast_id)},onMount(filter,updateFilter){broadcastPicker("#filter-broadcast",false,items=>{BroadcastsStore.itemsFetched(items)},{},{placeholder:__("Select a broadcast","groundhogg")}).on("select2:select",({target})=>{updateFilter({broadcast_id:parseInt($(target).val())})})},defaults:{broadcast_id:0},preload:({broadcast_id})=>{if(broadcast_id){return BroadcastsStore.maybeFetchItem(broadcast_id)}}});registerFilter("broadcast_link_clicked","broadcast",__("Broadcast Link Clicked","groundhogg"),{view({broadcast_id,link}){if(!broadcast_id&&!link){return __("Clicked any link in any broadcast","groundhogg")}if(!broadcast_id&&link){return sprintf(__("Clicked %s in any broadcast","groundhogg"),bold(link))}const broadcast=BroadcastsStore.get(broadcast_id);if(broadcast_id&&!link){return sprintf(__("Clicked any link in %1$s after %2$s","groundhogg"),bold(broadcast.object.data.title),bold(formatDateTime(broadcast.data.send_time*1e3)))}return sprintf(__("Clicked %1$s in %2$s after %3$s","groundhogg"),bold(link),bold(broadcast.object.data.title),bold(formatDateTime(broadcast.data.send_time*1e3)))},edit({broadcast_id,link}){return`
    5555            ${select({id:"filter-broadcast",name:"broadcast_id"},BroadcastsStore.getItems().map(b=>({value:b.ID,text:`${b.object.data.title} (${b.date_sent_pretty})`})),broadcast_id)}
    5656
    57             ${input({id:"filter-link",name:"link",value:link,autocomplete:"off",placeholder:__("Start typing to select a link or leave blank for any link","groundhogg")})}`},onMount(filter,updateFilter){broadcastPicker("#filter-broadcast",false,items=>{BroadcastsStore.itemsFetched(items)},{},{placeholder:__("Please select a broadcast or leave blank for any broadcast","groundhogg")}).on("change",e=>{updateFilter({broadcast_id:parseInt(e.target.value)})});linkPicker("#filter-link").on("change input blur",({target})=>{updateFilter({link:target.value})})},defaults:{link:"",broadcast_id:0},preload:({broadcast_id})=>{if(broadcast_id){return BroadcastsStore.maybeFetchItem(broadcast_id)}}});ContactFilterRegistry.registerFromProperties(Groundhogg.filters.gh_contact_custom_properties);const registerActivityFilter=(id,group,label,{view:view=()=>{},edit:edit=()=>{},onMount:onMount=()=>{},defaults:defaults={}})=>{registerFilter(id,group,label,{view(filter){return standardActivityDateTitle(filterCountTitle(view(filter),filter),filter)},edit(filter){return[edit(filter),filterCount(filter),standardActivityDateOptions(filter)].join("")},onMount(filter,updateFilter){onMount(filter,updateFilter);filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...defaults,...standardActivityDateDefaults,...filterCountDefaults}})};const registerActivityFilterWithValue=(id,group,label,{view:view=()=>{},edit:edit=()=>{},onMount:onMount=()=>{},defaults:defaults={},...rest})=>{registerFilter(id,group,label,{view(filter){let{value,value_compare}=filter;let content=view(filter);if(value&&value_compare){content+=` worth ${activityFilterComparisons[value_compare].toLowerCase()} ${value}`}return standardActivityDateTitle(filterCountTitle(content,filter),filter)},edit(filter){let{value,value_compare}=filter;return[edit(filter),`
     57            ${input({id:"filter-link",name:"link",value:link,autocomplete:"off",placeholder:__("Start typing to select a link or leave blank for any link","groundhogg")})}`},onMount(filter,updateFilter){broadcastPicker("#filter-broadcast",false,items=>{BroadcastsStore.itemsFetched(items)},{},{placeholder:__("Please select a broadcast or leave blank for any broadcast","groundhogg")}).on("change",e=>{updateFilter({broadcast_id:parseInt(e.target.value)})});linkPicker("#filter-link").on("change input blur",({target})=>{updateFilter({link:target.value})})},defaults:{link:"",broadcast_id:0},preload:({broadcast_id})=>{if(broadcast_id){return BroadcastsStore.maybeFetchItem(broadcast_id)}}});ContactFilterRegistry.registerFromProperties(Groundhogg.filters.gh_contact_custom_properties);const registerActivityFilter=(id,group,label,{view=()=>{},edit=()=>{},onMount=()=>{},defaults={}})=>{registerFilter(id,group,label,{view(filter){return standardActivityDateTitle(filterCountTitle(view(filter),filter),filter)},edit(filter){return[edit(filter),filterCount(filter),standardActivityDateOptions(filter)].join("")},onMount(filter,updateFilter){onMount(filter,updateFilter);filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...defaults,...standardActivityDateDefaults,...filterCountDefaults}})};const registerActivityFilterWithValue=(id,group,label,{view=()=>{},edit=()=>{},onMount=()=>{},defaults={},...rest})=>{registerFilter(id,group,label,{view(filter){let{value,value_compare}=filter;let content=view(filter);if(value&&value_compare){content+=` worth ${activityFilterComparisons[value_compare].toLowerCase()} ${value}`}return standardActivityDateTitle(filterCountTitle(content,filter),filter)},edit(filter){let{value,value_compare}=filter;return[edit(filter),`
    5858              <div class="space-between" style="gap: 10px">
    5959                  <span class="gh-text">Value</span>
     
    6363                  </div>
    6464              </div>
    65           `,filterCount(filter),standardActivityDateOptions(filter)].join("")},onMount(filter,updateFilter){onMount(filter,updateFilter);$("#filter-value,#filter-value-compare").on("change",e=>{updateFilter({[e.target.name]:e.target.value})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...defaults,...standardActivityDateDefaults,...filterCountDefaults,value:0,value_compare:"greater_than_or_equal_to"},...rest})};registerActivityFilterWithValue("custom_activity","activity",__("Custom Activity","groundhogg"),{view:({activity})=>`<b>${activity}</b>`,edit:({activity,...filter})=>{return[input({id:"filter-activity-type",name:"activity",value:activity,placeholder:"custom_activity"}),`<label>${__("Filter by activity meta","groundhogg")}</label>`,`<div id="custom-activity-meta-filters"></div>`].join("")},onMount(filter,updateFilter){$("#filter-activity-type").on("input",e=>{updateFilter({activity:e.target.value})});let{meta_filters:meta_filters=[]}=filter;inputRepeater("#custom-activity-meta-filters",{rows:meta_filters,cells:[props=>input({placeholder:"Key",className:"input",...props}),({value,...props})=>select({selected:value,options:AllComparisons,...props}),props=>input({placeholder:"Value",className:"input",...props})],addRow:()=>["","equals",""],onChange:rows=>{updateFilter({meta_filters:rows})}}).mount()},defaults:{activity:"",meta_filters:[]}});registerFilterGroup("query","Query");registerFilter("saved_search","query",__("Saved Search"),{view:({compare:compare="in",search})=>{return sprintf(__("Is %s search %s"),compare==="in"?"in":"not in",bold(SearchesStore.get(search)?.name))},edit:({compare})=>{return[select({name:"filter_compare",id:"filter-compare",options:{in:__("In"),not_in:__("Not in")},selected:compare}),select({name:"filter_search",id:"filter-search"})].join("")},onMount:({search},updateFilter)=>{SearchesStore.maybeFetchItems().then(items=>{$("#filter-search").select2({data:[{id:"",text:""},...items.map(({id,name})=>({id:id,text:name,selected:id===search}))],placeholder:__("Type to search...")}).on("change",e=>{updateFilter({search:e.target.value})})});$("#filter-compare").on("change",e=>{updateFilter({compare:e.target.value})})},defaults:{compare:"in",search:null},preload:({search})=>{if(!SearchesStore.hasItems()){return SearchesStore.fetchItems([])}}});ContactFilterRegistry.registerFilter(createFilter("sub_query","Sub Query","query",{display:({include_filters:include_filters=[],exclude_filters:exclude_filters=[]})=>{let texts=[ContactFilterRegistry.displayFilters(include_filters),ContactFilterRegistry.displayFilters(exclude_filters)];if(include_filters.length&&exclude_filters.length){return texts.join(' <abbr title="exclude">and exclude</abbr> ')}if(exclude_filters.length){return sprintf('<abbr title="exclude">Exclude</abbr> %s',texts[1])}if(include_filters.length){return texts[0]}throw new Error("No filters defined.")},edit:({include_filters:include_filters=[],exclude_filters:exclude_filters=[],updateFilter})=>{return Fragment([Div({className:"include-search-filters"},[Filters({id:"sub-query-filters",filters:include_filters,filterRegistry:ContactFilterRegistry,onChange:include_filters=>updateFilter({include_filters:include_filters})})]),Div({className:"exclude-search-filters"},[Filters({id:"sub-query-exclude-filters",filters:exclude_filters,filterRegistry:ContactFilterRegistry,onChange:exclude_filters=>updateFilter({exclude_filters:exclude_filters})})])])},preload:({include_filters:include_filters=[],exclude_filters:exclude_filters=[]})=>{return Promise.all([ContactFilterRegistry.preloadFilters(include_filters),ContactFilterRegistry.preloadFilters(exclude_filters)])}},{}));ContactFilterRegistry.registerFilter(createFilter("secondary_related","Is Child Of","query",{edit:({object_type:object_type="",object_id:object_id="",updateFilter})=>Fragment([Input({id:"object-type",name:"object_type",value:object_type,placeholder:"Parent Type",onInput:e=>{updateFilter({object_type:e.target.value})}}),Input({type:"number",id:"object-id",name:"object_id",value:object_id,placeholder:"Parent ID",min:0,onInput:e=>{updateFilter({object_id:e.target.value})}})]),display:({object_type,object_id})=>{if(!object_type){throw new Error("Type be defined")}if(!object_id){return`Is a child of ${object_type}`}return`Is a child of ${object_type} with ID ${object_id}`}},{object_type:"contact"}));ContactFilterRegistry.registerFilter(createFilter("primary_related","Is Parent Of","query",{edit:({object_type:object_type="",object_id:object_id="",updateFilter})=>Fragment([Input({id:"object-type",name:"object_type",value:object_type,placeholder:"Child Type",onInput:e=>{updateFilter({object_type:e.target.value})}}),Input({type:"number",id:"object-id",name:"object_id",value:object_id,placeholder:"Child ID",min:0,onInput:e=>{updateFilter({object_id:e.target.value})}})]),display:({object_type,object_id})=>{if(!object_type){throw new Error("Type must be defined")}if(!object_id){return`Is a parent of ${object_type}`}return`Is a parent of ${object_type} with ID ${object_id}`}},{object_type:"contact"}));registerFilterGroup("date","Date");const CurrentDateCompareFilterFactory=(id,name,type,formatter)=>createFilter(id,name,"date",{edit:({compare:compare="",after:after="",before:before="",updateFilter})=>Fragment([Select({id:"select-compare",selected:compare,options:{after:"After",before:"Before",between:"Between"},onChange:e=>{updateFilter({compare:e.target.value})}}),compare==="before"?null:Input({type:type,id:"after-date",name:"after_date",value:after,placeholder:"After...",onChange:e=>{updateFilter({after:e.target.value})}}),compare==="after"?null:Input({type:type,id:"before-date",name:"before_date",value:before,placeholder:"Before...",min:0,onInput:e=>{updateFilter({before:e.target.value})}})]),display:({compare:compare="",after,before})=>{let prefix=`<b>${name}</b>`;switch(compare){case"between":return ComparisonsTitleGenerators.between(prefix,formatter(after),formatter(before));case"after":return ComparisonsTitleGenerators.after(prefix,formatter(after));case"before":return ComparisonsTitleGenerators.before(prefix,formatter(before));default:throw new Error("Invalid date comparison.")}}},{compare:"between",before:"",after:""});ContactFilterRegistry.registerFilter(CurrentDateCompareFilterFactory("current_datetime","Current Date & Time","datetime-local",formatDateTime));ContactFilterRegistry.registerFilter(CurrentDateCompareFilterFactory("current_date","Current Date","date",formatDate));ContactFilterRegistry.registerFilter(CurrentDateCompareFilterFactory("current_time","Current Time","time",time=>formatTime(`2000-01-01T${time}`)));registerFilterGroup("submissions","Submissions");const SubmissionMetaFilters=(meta_filters,updateFilter)=>InputRepeater({id:"submission-meta-filters",rows:meta_filters,cells:[props=>Input({...props,placeholder:"Field Name"}),({value,...props})=>Select({selected:value,options:AllComparisons,...props}),props=>Input({...props,placeholder:"Value"})],fillRow:()=>["","equals",""],onChange:rows=>{updateFilter({meta_filters:rows})}});ContactFilterRegistry.registerFilter(createPastDateFilter("form_submissions","Form Submissions","submissions",{display:({form_id:form_id=[]})=>{if(!form_id.length){return"Submitted any form"}return`Submitted ${orList(form_id.map(id=>bold(Groundhogg.stores.forms.get(id).name)))}`},preload:({form_id:form_id=[]})=>{if(form_id.length){return Groundhogg.stores.forms.maybeFetchItems(form_id)}},edit:({form_id:form_id=[],meta_filters:meta_filters=[],updateFilter:updateFilter=()=>{}})=>{return Fragment([ItemPicker({id:"select-form",noneSelected:"Any form",fetchOptions:async search=>{let forms=await Groundhogg.stores.forms.fetchItems({search:search});return forms.map(item=>({id:item.ID,text:item.name}))},selected:form_id.map(id=>({id:id,text:Groundhogg.stores.forms.get(id).name})),onChange:items=>{updateFilter({form_id:items.map(item=>item.id)})}}),`<label>${__("Filter by fields","groundhogg")}</label>`,SubmissionMetaFilters(meta_filters,updateFilter)])}},{form_id:[],meta_filters:[]}));const StepPicker=(type,step_id,updateFilter)=>ItemPicker({id:"select-webhook",noneSelected:"Any webhook",fetchOptions:async search=>{let steps=await Groundhogg.stores.steps.fetchItems({search:search,step_type:type,status:"active"});return steps.map(item=>({id:item.ID,text:item.data.step_title}))},selected:step_id.map(id=>({id:id,text:Groundhogg.stores.steps.get(id).data.step_title})),onChange:items=>{updateFilter({step_id:items.map(item=>item.id)})}});if(typeof Groundhogg.rawStepTypes.http_post!=="undefined"){ContactFilterRegistry.registerFilter(createPastDateFilter("webhook_response","Webhook Response","submissions",{display:({step_id:step_id=[]})=>{if(!step_id.length){return"Any webhook response"}return`Webhook response from ${orList(step_id.map(id=>bold(Groundhogg.stores.steps.get(id).data.step_title)))}`},preload:({step_id:step_id=[]})=>{if(step_id.length){return Groundhogg.stores.steps.maybeFetchItems(step_id)}},edit:({step_id:step_id=[],meta_filters:meta_filters=[],updateFilter:updateFilter=()=>{}})=>{return Fragment([StepPicker("http_post",step_id,updateFilter),`<label>${__("Filter by fields","groundhogg")}</label>`,SubmissionMetaFilters(meta_filters,updateFilter)])}},{step_id:[],meta_filters:[]}))}if(typeof Groundhogg.rawStepTypes.webhook_listener!=="undefined"){ContactFilterRegistry.registerFilter(createPastDateFilter("webhook_request","Webhook Request","submissions",{display:({step_id:step_id=[]})=>{if(!step_id.length){return"Any webhook request"}return`Webhook request to ${orList(step_id.map(id=>bold(Groundhogg.stores.steps.get(id).data.step_title)))}`},preload:({step_id:step_id=[]})=>{if(step_id.length){return Groundhogg.stores.steps.maybeFetchItems(step_id)}},edit:({step_id:step_id=[],meta_filters:meta_filters=[],updateFilter:updateFilter=()=>{}})=>{return Fragment([StepPicker("webhook_listener",step_id,updateFilter),`<label>${__("Filter by fields","groundhogg")}</label>`,SubmissionMetaFilters(meta_filters,updateFilter)])}},{step_id:[],meta_filters:[]}))}if(!Groundhogg.filters){Groundhogg.filters={}}Groundhogg.filters.ContactFilters=ContactFilters;Groundhogg.filters.ContactFilterDisplay=ContactFilterDisplay;Groundhogg.filters.ContactFilterRegistry=ContactFilterRegistry;Groundhogg.filters.functions={createFilters:createFilters,registerFilter:registerFilter,registerFilterGroup:registerFilterGroup,ComparisonsTitleGenerators:ComparisonsTitleGenerators,AllComparisons:AllComparisons,NumericComparisons:NumericComparisons,StringComparisons:StringComparisons,standardActivityDateOptions:standardActivityDateOptions,standardActivityDateTitle:standardActivityDateTitle,standardActivityDateDefaults:standardActivityDateDefaults,standardActivityDateFilterOnMount:standardActivityDateFilterOnMount,BasicTextFilter:BasicTextFilter,registerActivityFilter:registerActivityFilter,registerActivityFilterWithValue:registerActivityFilterWithValue}})(jQuery);
     65          `,filterCount(filter),standardActivityDateOptions(filter)].join("")},onMount(filter,updateFilter){onMount(filter,updateFilter);$("#filter-value,#filter-value-compare").on("change",e=>{updateFilter({[e.target.name]:e.target.value})});filterCountOnMount(updateFilter);standardActivityDateFilterOnMount(filter,updateFilter)},defaults:{...defaults,...standardActivityDateDefaults,...filterCountDefaults,value:0,value_compare:"greater_than_or_equal_to"},...rest})};registerActivityFilterWithValue("custom_activity","activity",__("Custom Activity","groundhogg"),{view:({activity})=>`<b>${activity}</b>`,edit:({activity,...filter})=>{return[input({id:"filter-activity-type",name:"activity",value:activity,placeholder:"custom_activity"}),`<label>${__("Filter by activity meta","groundhogg")}</label>`,`<div id="custom-activity-meta-filters"></div>`].join("")},onMount(filter,updateFilter){$("#filter-activity-type").on("input",e=>{updateFilter({activity:e.target.value})});let{meta_filters=[]}=filter;inputRepeater("#custom-activity-meta-filters",{rows:meta_filters,cells:[props=>input({placeholder:"Key",className:"input",...props}),({value,...props})=>select({selected:value,options:AllComparisons,...props}),props=>input({placeholder:"Value",className:"input",...props})],addRow:()=>["","equals",""],onChange:rows=>{updateFilter({meta_filters:rows})}}).mount()},defaults:{activity:"",meta_filters:[]}});registerFilterGroup("query","Query");registerFilter("saved_search","query",__("Saved Search"),{view:({compare="in",search})=>{return sprintf(__("Is %s search %s"),compare==="in"?"in":"not in",bold(SearchesStore.get(search)?.name))},edit:({compare})=>{return[select({name:"filter_compare",id:"filter-compare",options:{in:__("In"),not_in:__("Not in")},selected:compare}),select({name:"filter_search",id:"filter-search"})].join("")},onMount:({search},updateFilter)=>{SearchesStore.maybeFetchItems().then(items=>{$("#filter-search").select2({data:[{id:"",text:""},...items.map(({id,name})=>({id:id,text:name,selected:id===search}))],placeholder:__("Type to search...")}).on("change",e=>{updateFilter({search:e.target.value})})});$("#filter-compare").on("change",e=>{updateFilter({compare:e.target.value})})},defaults:{compare:"in",search:null},preload:({search})=>{if(!SearchesStore.hasItems()){return SearchesStore.fetchItems([])}}});ContactFilterRegistry.registerFilter(createFilter("sub_query","Sub Query","query",{display:({include_filters=[],exclude_filters=[]})=>{let texts=[ContactFilterRegistry.displayFilters(include_filters),ContactFilterRegistry.displayFilters(exclude_filters)];if(include_filters.length&&exclude_filters.length){return texts.join(' <abbr title="exclude">and exclude</abbr> ')}if(exclude_filters.length){return sprintf('<abbr title="exclude">Exclude</abbr> %s',texts[1])}if(include_filters.length){return texts[0]}throw new Error("No filters defined.")},edit:({include_filters=[],exclude_filters=[],updateFilter})=>{return Fragment([Div({className:"include-search-filters"},[Filters({id:"sub-query-filters",filters:include_filters,filterRegistry:ContactFilterRegistry,onChange:include_filters=>updateFilter({include_filters:include_filters})})]),Div({className:"exclude-search-filters"},[Filters({id:"sub-query-exclude-filters",filters:exclude_filters,filterRegistry:ContactFilterRegistry,onChange:exclude_filters=>updateFilter({exclude_filters:exclude_filters})})])])},preload:({include_filters=[],exclude_filters=[]})=>{return Promise.all([ContactFilterRegistry.preloadFilters(include_filters),ContactFilterRegistry.preloadFilters(exclude_filters)])}},{}));ContactFilterRegistry.registerFilter(createFilter("secondary_related","Is Child Of","query",{edit:({object_type="",object_id="",updateFilter})=>Fragment([Input({id:"object-type",name:"object_type",value:object_type,placeholder:"Parent Type",onInput:e=>{updateFilter({object_type:e.target.value})}}),Input({type:"number",id:"object-id",name:"object_id",value:object_id,placeholder:"Parent ID",min:0,onInput:e=>{updateFilter({object_id:e.target.value})}})]),display:({object_type,object_id})=>{if(!object_type){throw new Error("Type be defined")}if(!object_id){return`Is a child of ${object_type}`}return`Is a child of ${object_type} with ID ${object_id}`}},{object_type:"contact"}));ContactFilterRegistry.registerFilter(createFilter("primary_related","Is Parent Of","query",{edit:({object_type="",object_id="",updateFilter})=>Fragment([Input({id:"object-type",name:"object_type",value:object_type,placeholder:"Child Type",onInput:e=>{updateFilter({object_type:e.target.value})}}),Input({type:"number",id:"object-id",name:"object_id",value:object_id,placeholder:"Child ID",min:0,onInput:e=>{updateFilter({object_id:e.target.value})}})]),display:({object_type,object_id})=>{if(!object_type){throw new Error("Type must be defined")}if(!object_id){return`Is a parent of ${object_type}`}return`Is a parent of ${object_type} with ID ${object_id}`}},{object_type:"contact"}));registerFilterGroup("date","Date");const CurrentDateCompareFilterFactory=(id,name,type,formatter)=>createFilter(id,name,"date",{edit:({compare="",after="",before="",updateFilter})=>Fragment([Select({id:"select-compare",selected:compare,options:{after:"After",before:"Before",between:"Between"},onChange:e=>{updateFilter({compare:e.target.value})}}),compare==="before"?null:Input({type:type,id:"after-date",name:"after_date",value:after,placeholder:"After...",onChange:e=>{updateFilter({after:e.target.value})}}),compare==="after"?null:Input({type:type,id:"before-date",name:"before_date",value:before,placeholder:"Before...",min:0,onInput:e=>{updateFilter({before:e.target.value})}})]),display:({compare="",after,before})=>{let prefix=`<b>${name}</b>`;switch(compare){case"between":return ComparisonsTitleGenerators.between(prefix,formatter(after),formatter(before));case"after":return ComparisonsTitleGenerators.after(prefix,formatter(after));case"before":return ComparisonsTitleGenerators.before(prefix,formatter(before));default:throw new Error("Invalid date comparison.")}}},{compare:"between",before:"",after:""});ContactFilterRegistry.registerFilter(CurrentDateCompareFilterFactory("current_datetime","Current Date & Time","datetime-local",formatDateTime));ContactFilterRegistry.registerFilter(CurrentDateCompareFilterFactory("current_date","Current Date","date",formatDate));ContactFilterRegistry.registerFilter(CurrentDateCompareFilterFactory("current_time","Current Time","time",time=>formatTime(`2000-01-01T${time}`)));const dayList={0:__("Sunday"),1:__("Monday"),2:__("Tuesday"),3:__("Wednesday"),4:__("Thursday"),5:__("Friday"),6:__("Saturday")};ContactFilterRegistry.registerFilter(createFilter("day_of_week","Day of Week","date",{edit:({days=[],updateFilter})=>{return ItemPicker({id:"days-of-week-picker",noneSelected:"Select a day",fetchOptions:async search=>assoc2array(dayList).filter(option=>option.text.match(new RegExp(search,"i"))),selected:days.map(day=>({id:day,text:dayList[day]})),onChange:items=>{updateFilter({days:items.map(item=>item.id)})}})},display:({days=[]})=>sprintf(__("Today is a %s"),orList(days.map(day=>bold(dayList[day]))))}));const dateList={1:__("1st"),2:__("2nd"),3:__("3rd"),4:__("4th"),5:__("5th"),6:__("6th"),7:__("7th"),8:__("8th"),9:__("9th"),10:__("10th"),11:__("11th"),12:__("12th"),13:__("13th"),14:__("14th"),15:__("15th"),16:__("16th"),17:__("17th"),18:__("18th"),19:__("19th"),20:__("20th"),21:__("21st"),22:__("22nd"),23:__("23rd"),24:__("24th"),25:__("25th"),26:__("26th"),27:__("27th"),28:__("28th"),29:__("29th"),30:__("30th"),31:__("31st"),0:__("Last")};ContactFilterRegistry.registerFilter(createFilter("day_of_month","Day of Month","date",{edit:({dates=[],updateFilter})=>{return ItemPicker({id:"days-of-week-picker",noneSelected:"Select a day",fetchOptions:async search=>assoc2array(dateList).filter(option=>option.text.match(new RegExp(search,"i"))),selected:dates.map(date=>({id:date,text:dateList[date]})),onChange:items=>{updateFilter({dates:items.map(item=>item.id)})}})},display:({dates=[]})=>sprintf(__("Today is the %s of the month"),orList(dates.map(date=>bold(dateList[date]))))}));registerFilterGroup("submissions","Submissions");const SubmissionMetaFilters=(meta_filters,updateFilter)=>InputRepeater({id:"submission-meta-filters",rows:meta_filters,cells:[props=>Input({...props,placeholder:"Field Name"}),({value,...props})=>Select({selected:value,options:AllComparisons,...props}),props=>Input({...props,placeholder:"Value"})],fillRow:()=>["","equals",""],onChange:rows=>{updateFilter({meta_filters:rows})}});ContactFilterRegistry.registerFilter(createPastDateFilter("form_submissions","Form Submissions","submissions",{display:({form_id=[]})=>{if(!form_id.length){return"Submitted any form"}return`Submitted ${orList(form_id.map(id=>bold(Groundhogg.stores.forms.get(id).name)))}`},preload:({form_id=[]})=>{if(form_id.length){return Groundhogg.stores.forms.maybeFetchItems(form_id)}},edit:({form_id=[],meta_filters=[],updateFilter=()=>{}})=>{return Fragment([ItemPicker({id:"select-form",noneSelected:"Any form",fetchOptions:async search=>{let forms=await Groundhogg.stores.forms.fetchItems({search:search});return forms.map(item=>({id:item.ID,text:item.name}))},selected:form_id.map(id=>({id:id,text:Groundhogg.stores.forms.get(id).name})),onChange:items=>{updateFilter({form_id:items.map(item=>item.id)})}}),`<label>${__("Filter by fields","groundhogg")}</label>`,SubmissionMetaFilters(meta_filters,updateFilter)])}},{form_id:[],meta_filters:[]}));const StepPicker=(type,step_id,updateFilter)=>ItemPicker({id:"select-webhook",noneSelected:"Any webhook",fetchOptions:async search=>{let steps=await Groundhogg.stores.steps.fetchItems({search:search,step_type:type,status:"active"});return steps.map(item=>({id:item.ID,text:item.data.step_title}))},selected:step_id.map(id=>({id:id,text:Groundhogg.stores.steps.get(id).data.step_title})),onChange:items=>{updateFilter({step_id:items.map(item=>item.id)})}});if(typeof Groundhogg.rawStepTypes.http_post!=="undefined"){ContactFilterRegistry.registerFilter(createPastDateFilter("webhook_response","Webhook Response","submissions",{display:({step_id=[]})=>{if(!step_id.length){return"Any webhook response"}return`Webhook response from ${orList(step_id.map(id=>bold(Groundhogg.stores.steps.get(id).data.step_title)))}`},preload:({step_id=[]})=>{if(step_id.length){return Groundhogg.stores.steps.maybeFetchItems(step_id)}},edit:({step_id=[],meta_filters=[],updateFilter=()=>{}})=>{return Fragment([StepPicker("http_post",step_id,updateFilter),`<label>${__("Filter by fields","groundhogg")}</label>`,SubmissionMetaFilters(meta_filters,updateFilter)])}},{step_id:[],meta_filters:[]}))}ContactFilterRegistry.registerFilter(createPastDateFilter("wp_fusion_activity","WP Fusion","activity",{display:({event_name="",event_name_compare,event_value="",event_value_compare})=>{if(!event_name){return"Any WP Fusion activity"}let text=sprintf(`WP Fusion Event: %s`,ComparisonsTitleGenerators[event_name_compare](bold("Name"),`<code>${event_name}</code>`));if(event_value){text+=", "+ComparisonsTitleGenerators[event_value_compare](bold("Value"),`<code>${event_value}</code>`)}return text},edit:({event_name="",event_value="",event_value_compare="equals",event_name_compare="equals",updateFilter=()=>{}})=>{return Fragment([MakeEl.Label({for:"event-name"},"Event Name"),MakeEl.InputGroup([Select({id:"event-name-compare",name:"event_name_compare",selected:event_name_compare,options:StringComparisons,onChange:e=>{updateFilter({event_name_compare:e.target.value})}}),Input({id:"event-name",name:"event_name",value:event_name,placeholder:"Event Name",onChange:e=>{updateFilter({event_name:e.target.value})}})]),MakeEl.Label({for:"event-value"},"Event Value"),MakeEl.InputGroup([Select({id:"event-value-compare",selected:event_value_compare,options:AllComparisons,onChange:e=>{updateFilter({event_value_compare:e.target.value})}}),Input({id:"event-value",value:event_value,placeholder:"Event value",onChange:e=>{updateFilter({event_value:e.target.value})}})])])}},{event_name_compare:"equals",event_name:"",event_value_compare:"equals",event_value:""}));if(typeof Groundhogg.rawStepTypes.webhook_listener!=="undefined"){ContactFilterRegistry.registerFilter(createPastDateFilter("webhook_request","Webhook Request","submissions",{display:({step_id=[]})=>{if(!step_id.length){return"Any webhook request"}return`Webhook request to ${orList(step_id.map(id=>bold(Groundhogg.stores.steps.get(id).data.step_title)))}`},preload:({step_id=[]})=>{if(step_id.length){return Groundhogg.stores.steps.maybeFetchItems(step_id)}},edit:({step_id=[],meta_filters=[],updateFilter=()=>{}})=>{return Fragment([StepPicker("webhook_listener",step_id,updateFilter),`<label>${__("Filter by fields","groundhogg")}</label>`,SubmissionMetaFilters(meta_filters,updateFilter)])}},{step_id:[],meta_filters:[]}))}if(!Groundhogg.filters){Groundhogg.filters={}}Groundhogg.filters.ContactFilters=ContactFilters;Groundhogg.filters.ContactFilterDisplay=ContactFilterDisplay;Groundhogg.filters.ContactFilterRegistry=ContactFilterRegistry;Groundhogg.filters.functions={createFilters:createFilters,registerFilter:registerFilter,registerFilterGroup:registerFilterGroup,ComparisonsTitleGenerators:ComparisonsTitleGenerators,AllComparisons:AllComparisons,NumericComparisons:NumericComparisons,StringComparisons:StringComparisons,standardActivityDateOptions:standardActivityDateOptions,standardActivityDateTitle:standardActivityDateTitle,standardActivityDateDefaults:standardActivityDateDefaults,standardActivityDateFilterOnMount:standardActivityDateFilterOnMount,BasicTextFilter:BasicTextFilter,registerActivityFilter:registerActivityFilter,registerActivityFilterWithValue:registerActivityFilterWithValue}})(jQuery);
  • groundhogg/trunk/db/query/filters.php

    r3343709 r3400645  
    614614                $where->notContains( $column, $value );
    615615                break;
     616            case '^':
    616617            case 'starts_with':
    617618            case 'begins_with':
     
    621622                $where->notLike( $column, $where->esc_like( $value ) . '%' );
    622623                break;
     624            case '$':
    623625            case 'ends_with':
    624626                $where->endsWith( $column, $value );
  • groundhogg/trunk/db/query/where.php

    r3343709 r3400645  
    269269    public function compare( $column, $value, $compare = '=', $format = false ) {
    270270
     271        // handle other comparisons by mapping to other functions
     272        switch ( strtolower( $compare ) ) {
     273            case 'contains':
     274                return $this->contains( $column, $value );
     275            case 'not_contains':
     276                return $this->notContains( $column, $value );
     277            case '^':
     278            case 'starts_with':
     279            case 'begins_with':
     280                return $this->startsWith( $column, $value );
     281            case '$':
     282            case 'ends_with':
     283                return $this->endsWith( $column, $value );
     284            case 'does_not_start_with':
     285                return $this->notLike( $column, $this->esc_like( $value ) . '%' );
     286            case 'does_not_end_with':
     287                return $this->notLike( $column, '%' . $this->esc_like( $value ) );
     288            case 'empty':
     289                return $this->empty( $column );
     290            case 'not_empty':
     291                return $this->notEmpty( $column );
     292        }
     293
    271294        $column  = $this->sanitize_column( $column );
    272295        $compare = $this->symbolize_comparison( $compare );
  • groundhogg/trunk/groundhogg.php

    r3395861 r3400645  
    44 * Plugin URI: https://www.groundhogg.io/?utm_source=wp-plugins&utm_campaign=plugin-uri&utm_medium=wp-dash
    55 * Description: CRM and marketing automation for WordPress
    6  * Version: 4.2.8
     6 * Version: 4.2.9
    77 * Author: Groundhogg Inc.
    88 * Author URI: https://www.groundhogg.io/?utm_source=wp-plugins&utm_campaign=author-uri&utm_medium=wp-dash
     
    2525if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
    2626
    27 define( 'GROUNDHOGG_VERSION', '4.2.8' );
    28 define( 'GROUNDHOGG_PREVIOUS_STABLE_VERSION', '4.2.7' );
     27define( 'GROUNDHOGG_VERSION', '4.2.9' );
     28define( 'GROUNDHOGG_PREVIOUS_STABLE_VERSION', '4.2.8' );
    2929
    3030define( 'GROUNDHOGG__FILE__', __FILE__ );
  • groundhogg/trunk/includes/contact-query.php

    r3343709 r3400645  
    11541154
    11551155            $alias = $activityQuery->joinMeta( $key );
    1156             $activityQuery->where()->compare( "$alias.meta_value", $value, $compare );
     1156
     1157            Filters::string( "$alias.meta_value", [
     1158                'compare' => $compare,
     1159                'value'   => $value
     1160            ], $activityQuery->where() );
     1161        }
     1162    }
     1163
     1164    /**
     1165     * Special handler for WPFusion activity
     1166     *
     1167     * @throws \Exception
     1168     *
     1169     * @param  Where  $where
     1170     * @param $filter
     1171     *
     1172     * @return void
     1173     */
     1174    public static function filter_wp_fusion_activity( $filter, Where $where ) {
     1175
     1176        $filter = wp_parse_args( $filter, [
     1177            'event_name'          => '',
     1178            'event_name_compare'  => 'equals',
     1179            'event_value'         => '',
     1180            'event_value_compare' => 'equals'
     1181        ] );
     1182
     1183        $activityQuery = self::basic_activity_filter( 'wp_fusion', $filter, $where );
     1184
     1185        if ( ! empty( $filter['event_name'] ) ){
     1186            $alias = $activityQuery->joinMeta( 'event_name' );
     1187
     1188            Filters::string( "$alias.meta_value", [
     1189                'compare' => $filter['event_name_compare'],
     1190                'value'   => $filter['event_name']
     1191            ], $activityQuery->where() );
     1192        }
     1193
     1194        if ( ! empty( $filter['event_value'] ) ) {
     1195            $alias = $activityQuery->joinMeta( 'event_value' );
     1196
     1197            Filters::string( "$alias.meta_value", [
     1198                'compare' => $filter['event_value_compare'],
     1199                'value'   => $filter['event_value']
     1200            ], $activityQuery->where() );
    11571201        }
    11581202    }
     
    11961240
    11971241            $alias = $submissionQuery->joinMeta( $key );
    1198             $submissionQuery->where()->compare( "$alias.meta_value", $value, $compare );
     1242
     1243            Filters::string( "$alias.meta_value", [
     1244                'compare' => $compare,
     1245                'value'   => $value
     1246            ], $submissionQuery->where() );
     1247
    11991248        }
    12001249
     
    15381587
    15391588        self::filter_current_datetime( $filter, $where );
     1589    }
     1590
     1591    /**
     1592     * If today's date is a specific day of the week
     1593     *
     1594     * @param $filter
     1595     * @param  Where  $where
     1596     *
     1597     * @return void
     1598     */
     1599    public static function filter_day_of_week( $filter, Where $where ) {
     1600
     1601        $days = wp_parse_id_list( $filter['days'] );
     1602        $today = new DateTimeHelper();
     1603
     1604        if ( in_array( absint( $today->format( 'w') ), $days ) ){
     1605            $where->addCondition( '1=1' ); // always true
     1606        } else {
     1607            $where->addCondition( '0=1' ); // short circuit false
     1608        }
     1609    }
     1610
     1611    /**
     1612     * If today's date is a specific day of the month
     1613     *
     1614     * @param $filter
     1615     * @param  Where  $where
     1616     *
     1617     * @return void
     1618     */
     1619    public static function filter_day_of_month( $filter, Where $where ) {
     1620
     1621        $dates = wp_parse_id_list( $filter['dates'] );
     1622        $today = new DateTimeHelper();
     1623
     1624        // using last
     1625        if ( in_array( 0, $dates ) && $today->format( 'j' ) === $today->format('t') ){
     1626            $where->addCondition( '1=1' ); // always true
     1627            return;
     1628        }
     1629
     1630        if ( in_array( absint( $today->format( 'j') ), $dates ) ){
     1631            $where->addCondition( '1=1' ); // always true
     1632        } else {
     1633            $where->addCondition( '0=1' ); // short circuit false
     1634        }
    15401635    }
    15411636
  • groundhogg/trunk/includes/form/form-v2.php

    r3395861 r3400645  
    19291929        if ( isset_not_empty( $recaptcha, 'enabled' ) && is_recaptcha_enabled() ) {
    19301930            $html .= $this->render_field( $recaptcha );
     1931            wp_enqueue_script( 'groundhogg-google-recaptcha' );
    19311932        }
    19321933
    19331934        if ( isset_not_empty( $turnstile, 'enabled' ) && is_turnstile_enabled() ) {
    19341935            $html .= $this->render_field( $turnstile );
     1936            wp_enqueue_script( 'cf-turnstile' );
    19351937        }
    19361938
  • groundhogg/trunk/includes/scripts.php

    r3395861 r3400645  
    126126            ] );
    127127
    128             $form_v2_dependencies[] = 'google-recaptcha';
     128//          $form_v2_dependencies[] = 'google-recaptcha';
    129129            $form_dependencies[]    = 'groundhogg-google-recaptcha';
    130130        }
     
    132132        if ( is_turnstile_enabled() ){
    133133            wp_register_script( 'cf-turnstile', 'https://challenges.cloudflare.com/turnstile/v0/api.js' );
    134             $form_v2_dependencies[] = 'cf-turnstile';
     134//          $form_v2_dependencies[] = 'cf-turnstile';
    135135        }
    136136
Note: See TracChangeset for help on using the changeset viewer.