From 5dc6753c7151ac994c63e18914998991b1f65cbd Mon Sep 17 00:00:00 2001 From: Ben Harvey Date: Mon, 13 Oct 2025 23:01:46 +0100 Subject: [PATCH 01/29] Fix - CVE-2025-60868 --- src/Helpers/URISupport.php | 43 +++-------------------- src/Http/Middleware/CheckForRedirects.php | 34 ++++++++++++++---- 2 files changed, 31 insertions(+), 46 deletions(-) diff --git a/src/Helpers/URISupport.php b/src/Helpers/URISupport.php index a96326a..33c27d3 100644 --- a/src/Helpers/URISupport.php +++ b/src/Helpers/URISupport.php @@ -4,61 +4,26 @@ namespace AltDesign\AltRedirect\Helpers; -use Illuminate\Support\Arr; use Illuminate\Support\Str; class URISupport { /** - * Returns the current URI with named Query Strings filtered out . + * Returns the current URI without any query strings for redirect matching. * * @return string $uri */ public static function uriWithFilteredQueryStrings() : string { $request = request(); - $data = new Data('query-strings'); - $withoutQueryStrings = Arr::pluck($data->all(), 'query_string'); - // Filter out unwanted params, then strip the base url to get a filtered uri - $encoding = str_contains($request->getRequestURI(), '+') - ? PHP_QUERY_RFC1738 - : PHP_QUERY_RFC3986; + // Return just the path without any query parameters + // Query parameters will be handled separately in redirectWithPreservedParams return Str::replace( $request->root(), '', - self::fullUrlWithoutQuery($withoutQueryStrings, $encoding) + $request->url() ); } - /** - * Replacement for fullUrlWithoutQuery() in Request to use custom Arr::query() implementation - * - * @param array $keys - * @param int $encoding_type (optional) Encoding Type - * @return string - */ - private static function fullUrlWithoutQuery(array $keys, $encoding_type = PHP_QUERY_RFC1738) : string - { - $request = request(); - $query = Arr::except($request->query(), $keys); - - $question = $request->getBaseUrl().$request->getPathInfo() === '/' ? '/?' : '?'; - - return count($query) > 0 - ? $request->url().$question.self::myArrQuery($query, $encoding_type) - : $request->url(); - } - - /** - * Replacement for Arr::query() to use default encoding method - * - * @param array $array - * @param int $encoding_type (optional) Encoding Type - * @return string - */ - private static function myArrQuery(array $array, $encoding_type = PHP_QUERY_RFC1738) : string - { - return http_build_query($array, '', '&', $encoding_type); - } } diff --git a/src/Http/Middleware/CheckForRedirects.php b/src/Http/Middleware/CheckForRedirects.php index 54fe511..9598e9c 100644 --- a/src/Http/Middleware/CheckForRedirects.php +++ b/src/Http/Middleware/CheckForRedirects.php @@ -65,19 +65,39 @@ public function handle(Request $request, Closure $next, string ...$guards): Resp private function redirectWithPreservedParams($to, $status) { - $preserveKeys = []; + $stripKeys = []; foreach ((new Data('query-strings'))->all() as $item) { - if (!($item['strip'] ?? false)) { - $preserveKeys[] = $item['query_string']; + if ($item['strip'] ?? false) { + $stripKeys[] = strtolower($item['query_string']); } } + // Parse raw query string to handle double-encoding and duplicates + $rawQueryString = request()->getQueryString(); $filteredStrings = []; - foreach(request()->all() as $key => $value) { - if (!in_array($key, $preserveKeys)) { - continue; + $seenKeys = []; + + if ($rawQueryString) { + // Decode the query string recursively to handle multiple levels of encoding + $decodedQueryString = $rawQueryString; + $previousQueryString = ''; + + // Keep decoding until no more changes occur (handles double/triple encoding) + while ($decodedQueryString !== $previousQueryString) { + $previousQueryString = $decodedQueryString; + $decodedQueryString = urldecode($decodedQueryString); + } + + parse_str($decodedQueryString, $parsedParams); + + foreach($parsedParams as $key => $value) { + $normalizedKey = strtolower($key); + // Strip only parameters marked with strip:true, preserve all others + if (!in_array($normalizedKey, $stripKeys) && !isset($seenKeys[$normalizedKey])) { + $seenKeys[$normalizedKey] = true; + $filteredStrings[] = sprintf("%s=%s", urlencode($key), urlencode($value)); + } } - $filteredStrings[] = sprintf( "%s=%s", $key, $value); } if ($filteredStrings) { From bd4a454873cd820293e1ea16e03cfbc253e8d1af Mon Sep 17 00:00:00 2001 From: Ben Harvey Date: Mon, 13 Oct 2025 23:35:44 +0100 Subject: [PATCH 02/29] Create SECURITY.md --- SECURITY.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..94b97b9 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,30 @@ +# Reporting a Vulnerability + +We take security very seriously at Alt Design. If you discover a potential security vulnerability in this project, please report it **privately** to us rather than opening a public issue. + +### Contact + +Please send all security reports to: + +**Email:** ben@alt-design.net + +Include as much detail as possible, such as: + +- Steps to reproduce the issue +- Impact assessment +- Affected version(s) +- Any suggested mitigations (if known) + +We will acknowledge receipt of your report promptly and keep you updated on progress. + +### Response Time + +We aim to respond within 48 hours. Critical vulnerabilities may receive priority handling. + +### Public Disclosure + +After a fix has been released and verified, we may publicly disclose the vulnerability in a security advisory. We will give credit to reporters unless they request anonymity. + +### Security Updates + +We publish security updates as new releases. We strongly recommend users upgrade to the latest version to stay protected. From 0e85ac22a29759959f98c031ce142104883dc1c5 Mon Sep 17 00:00:00 2001 From: Alt-Charlie Date: Mon, 16 Feb 2026 15:14:31 +0000 Subject: [PATCH 03/29] Statamic V6 support --- .gitignore | 6 + composer.json | 4 +- package.json | 8 +- .../assets/alt-redirect-addon-4ed993c7.js | 1 - .../assets/alt-redirect-addon-Bj7zCgN-.js | 1 + .../assets/alt-redirect-addon-d5a1e6a6.js | 1 - .../assets/alt-redirect-addon-tn0RQdqM.css | 0 resources/dist/build/manifest.json | 15 +- resources/js/alt-redirect-addon.js | 2 +- resources/js/components/AltRedirect.vue | 374 ++++++++---------- resources/views/index.blade.php | 20 - .../Controllers/AltRedirectController.php | 24 +- vite.config.js | 4 +- 13 files changed, 196 insertions(+), 264 deletions(-) create mode 100644 .gitignore delete mode 100644 resources/dist/build/assets/alt-redirect-addon-4ed993c7.js create mode 100644 resources/dist/build/assets/alt-redirect-addon-Bj7zCgN-.js delete mode 100644 resources/dist/build/assets/alt-redirect-addon-d5a1e6a6.js create mode 100644 resources/dist/build/assets/alt-redirect-addon-tn0RQdqM.css delete mode 100644 resources/views/index.blade.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..31de4df --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +composer.lock +/node_modules +package-lock.json +/vendor +vite.hot +.DS_* \ No newline at end of file diff --git a/composer.json b/composer.json index b56c445..947ba0b 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ }, "require": { "php": "^8.1", - "statamic/cms": "^4.0|^5.17.0" + "statamic/cms": "^6.0" }, "extra": { "statamic": { @@ -24,7 +24,7 @@ }, "config": { "allow-plugins": { - "pixelfear/composer-dist-plugin": false + "pixelfear/composer-dist-plugin": true } } } diff --git a/package.json b/package.json index 1891427..4f68882 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,11 @@ "dev": "vite", "build": "vite build" }, + "dependencies": { + "@statamic/cms": "file:./vendor/statamic/cms/resources/dist-package" + }, "devDependencies": { - "@vitejs/plugin-vue2": "^2.2.0", - "laravel-vite-plugin": "^0.7.2", - "vite": "^4.0.0" + "laravel-vite-plugin": "^2.0.1", + "vite": "^7.3.1" } } diff --git a/resources/dist/build/assets/alt-redirect-addon-4ed993c7.js b/resources/dist/build/assets/alt-redirect-addon-4ed993c7.js deleted file mode 100644 index 8b13789..0000000 --- a/resources/dist/build/assets/alt-redirect-addon-4ed993c7.js +++ /dev/null @@ -1 +0,0 @@ - diff --git a/resources/dist/build/assets/alt-redirect-addon-Bj7zCgN-.js b/resources/dist/build/assets/alt-redirect-addon-Bj7zCgN-.js new file mode 100644 index 0000000..1cd3371 --- /dev/null +++ b/resources/dist/build/assets/alt-redirect-addon-Bj7zCgN-.js @@ -0,0 +1 @@ +const $=window.Vue,{BaseTransition:ue,BaseTransitionPropsValidators:de,Comment:ce,DeprecationTypes:pe,EffectScope:me,ErrorCodes:ge,ErrorTypeStrings:fe,Fragment:M,KeepAlive:Se,ReactiveEffect:ve,Static:ye,Suspense:he,Teleport:Ce,Text:we,TrackOpTypes:be,Transition:Te,TransitionGroup:xe,TriggerOpTypes:Pe,VueElement:Re,__esModule:ke,assertNumber:Ve,callWithAsyncErrorHandling:Ae,callWithErrorHandling:Ie,camelize:Me,capitalize:Ee,cloneVNode:Le,compatUtils:De,compile:He,computed:E,createApp:Fe,createBlock:_e,createCommentVNode:G,createElementBlock:d,createElementVNode:e,createHydrationRenderer:Be,createPropsRestProxy:ze,createRenderer:Ue,createSSRApp:qe,createSlots:Oe,createStaticVNode:$e,createTextVNode:f,createVNode:l,customRef:Ge,defineAsyncComponent:Ne,defineComponent:je,defineCustomElement:Ke,defineEmits:We,defineExpose:Qe,defineModel:Ye,defineOptions:Je,defineProps:Xe,defineSSRCustomElement:Ze,defineSlots:et,devtools:tt,effect:rt,effectScope:ot,getCurrentInstance:lt,getCurrentScope:nt,getCurrentWatcher:st,getTransitionRawChildren:at,guardReactiveProps:it,h:ut,handleError:dt,hasInjectionContext:ct,hydrate:pt,hydrateOnIdle:mt,hydrateOnInteraction:gt,hydrateOnMediaQuery:ft,hydrateOnVisible:St,initCustomFormatter:vt,initDirectivesForSSR:yt,inject:ht,isMemoSame:Ct,isProxy:wt,isReactive:bt,isReadonly:Tt,isRef:xt,isRuntimeOnly:Pt,isShallow:Rt,isVNode:kt,markRaw:Vt,mergeDefaults:At,mergeModels:It,mergeProps:Mt,nextTick:Et,nodeOps:Lt,normalizeClass:N,normalizeProps:Dt,normalizeStyle:Ht,onActivated:Ft,onBeforeMount:_t,onBeforeUnmount:Bt,onBeforeUpdate:zt,onDeactivated:Ut,onErrorCaptured:qt,onMounted:Ot,onRenderTracked:$t,onRenderTriggered:Gt,onScopeDispose:Nt,onServerPrefetch:jt,onUnmounted:Kt,onUpdated:Wt,onWatcherCleanup:Qt,openBlock:c,patchProp:Yt,popScopeId:Jt,provide:Xt,proxyRefs:Zt,pushScopeId:er,queuePostFlushCb:tr,reactive:rr,readonly:or,ref:p,registerRuntimeCompiler:lr,render:nr,renderList:L,renderSlot:sr,resolveComponent:ar,resolveDirective:ir,resolveDynamicComponent:ur,resolveFilter:dr,resolveTransitionHooks:cr,setBlockTracking:pr,setDevtoolsHook:mr,setTransitionHooks:gr,shallowReactive:fr,shallowReadonly:Sr,shallowRef:vr,ssrContextKey:yr,ssrUtils:hr,stop:Cr,toDisplayString:i,toHandlerKey:wr,toHandlers:br,toRaw:Tr,toRef:xr,toRefs:Pr,toValue:Rr,transformVNodeArgs:kr,triggerRef:Vr,unref:o,useAttrs:Ar,useCssModule:Ir,useCssVars:Mr,useHost:Er,useId:Lr,useModel:Dr,useSSRContext:Hr,useShadowRoot:Fr,useSlots:_r,useTemplateRef:Br,useTransitionState:zr,vModelCheckbox:Ur,vModelDynamic:qr,vModelRadio:Or,vModelSelect:$r,vModelText:Gr,vShow:Nr,version:jr,warn:Kr,watch:Wr,watchEffect:Qr,watchPostEffect:Yr,watchSyncEffect:Jr,withAsyncContext:Xr,withCtx:a,withDefaults:Zr,withDirectives:eo,withKeys:to,withMemo:ro,withModifiers:oo,withScopeId:lo}=$,{Alert:no,AuthCard:so,Avatar:ao,Badge:io,Button:S,ButtonGroup:uo,Calendar:co,Card:P,CardList:po,CardListItem:mo,CardPanel:go,CharacterCounter:fo,Checkbox:So,CheckboxGroup:vo,CodeEditor:yo,Combobox:ho,CommandPaletteItem:Co,ConfirmationModal:wo,Context:bo,ContextFooter:To,ContextHeader:xo,ContextItem:Po,ContextLabel:Ro,ContextMenu:ko,ContextSeparator:Vo,CreateForm:Ao,DatePicker:Io,DateRangePicker:Mo,Description:Eo,DocsCallout:Lo,DragHandle:Do,Dropdown:Ho,DropdownItem:Fo,DropdownLabel:_o,DropdownMenu:Bo,DropdownSeparator:zo,DropdownFooter:Uo,DropdownHeader:qo,Editable:Oo,ErrorMessage:$o,EmptyStateItem:Go,EmptyStateMenu:No,Field:jo,Header:j,Heading:D,HoverCard:Ko,Icon:Wo,Input:H,InputGroup:Qo,InputGroupAppend:Yo,InputGroupPrepend:Jo,Label:Xo,Listing:Zo,ListingCustomizeColumns:el,ListingFilters:tl,ListingHeaderCell:rl,ListingPagination:ol,ListingPresets:ll,ListingPresetTrigger:nl,ListingRowActions:sl,ListingSearch:al,ListingTable:il,ListingTableBody:ul,ListingTableHead:dl,ListingToggleAll:cl,LivePreview:pl,LivePreviewPopout:ml,Modal:gl,ModalClose:fl,ModalTitle:Sl,Pagination:K,Panel:vl,PanelFooter:yl,PanelHeader:hl,Popover:Cl,PublishComponents:wl,PublishContainer:W,publishContextKey:bl,injectPublishContext:Tl,PublishField:xl,PublishFields:Pl,PublishFieldsProvider:Rl,PublishForm:kl,PublishLocalizations:Vl,PublishSections:Al,PublishTabs:Il,Radio:Ml,RadioGroup:El,Select:Ll,Separator:Dl,Slider:Hl,Skeleton:Fl,SplitterGroup:_l,SplitterPanel:Bl,SplitterResizeHandle:zl,StatusIndicator:Ul,Subheading:F,Switch:Q,TabContent:ql,Stack:Ol,StackClose:$l,StackHeader:Gl,StackFooter:Nl,StackContent:jl,Table:Kl,TableCell:Wl,TableColumn:Ql,TableColumns:Yl,TableRow:Jl,TableRows:Xl,TabList:Zl,TabProvider:en,Tabs:tn,TabTrigger:rn,Textarea:on,TimePicker:ln,ToggleGroup:nn,ToggleItem:sn,Widget:an,registerIconSet:un,registerIconSetFromStrings:dn}=__STATAMIC__.ui,{AfterSaveHooks:Y,BeforeSaveHooks:J,Pipeline:X,PipelineStopped:cn,Request:Z}=__STATAMIC__.savePipeline,{Form:pn,Head:mn,Link:gn,router:v,toggleArchitecturalBackground:fn,useArchitecturalBackground:Sn,useForm:vn,usePoll:yn}=__STATAMIC__.inertia,ee={id:"alt-redirect"},te={class:"text-sm"},re={class:"my-4 pb-2 px-4"},oe={class:"px-2"},le={key:0,"data-size":"sm",tabindex:"0",class:"data-table",style:{"table-layout":"fixed"}},ne={key:1,"data-size":"sm",tabindex:"0",class:"data-table",style:{"table-layout":"fixed"}},se=["href"],ae={class:"flex justify-between items-center"},R=10,ie={__name:"AltRedirect",props:{title:String,instructions:String,action:String,blueprint:Array,initialMeta:Array,initialValues:Array,items:Array,type:String},setup(s){const m=s,u=p(1),C=p(null),y=p(""),w=p({...m.initialValues}),_=m.initialMeta,k=p({}),V=p(!1),A=p("container"),b=E(()=>Math.ceil(m.items.length/R)),I=E(()=>{let n=m.items;y.value?.length>0&&(n=n.filter(T=>Object.values(T).map(x=>x?.toString().toLowerCase()).some(x=>x?.includes(y.value.toLowerCase()))));const r=(u.value-1)*R,t=r+R;return n.slice(r,t)});function g(n){n>b.value&&(n=b.value),u.value=n}function B(n,r){confirm("Are you sure you want to delete this redirect?")&&v.post(cp_url("alt-design/alt-redirect/delete"),{from:n,id:r},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("Redirect deleted successfully!"),g(u.value)}})}function z(n){confirm("Are you sure you want to delete this query string?")&&v.post(cp_url("/alt-design/alt-redirect/query-strings/delete"),{query_string:n},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("Query string deleted successfully!"),g(u.value)}})}function U(){if(!C.value){alert("You haven't attached a CSV file!");return}v.post(cp_url("alt-design/alt-redirect/import"),{file:C.value},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("CSV imported successfully!"),g(u.value)}})}function q(n,r){v.post(cp_url("/alt-design/alt-redirect/query-strings/toggle"),{index:n,toggleKey:r},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("Toggled successfully!"),g(u.value)}})}function O(){new X().provide({container:A,errors:k,saving:V}).through([new J("alt-redirect"),new Z(cp_url("/alt-design/alt-redirect"),"POST",{type:m.type}),new Y("alt-redirect")]).then(()=>{w.value={...m.initialValues},Statamic.$toast.success("Redirect added successfully!"),v.reload()})}return(n,r)=>(c(),d("div",ee,[l(o(j),{title:s.title},{title:a(()=>[e("div",null,[f(i(s.title)+" ",1),e("div",te,i(s.instructions),1)])]),default:a(()=>[l(o(S),{text:"Save",variant:"primary",disabled:V.value,onClick:O},null,8,["disabled"])]),_:1},8,["title"]),l(o(W),{ref_key:"container",ref:A,action:s.action,blueprint:s.blueprint,meta:o(_),modelValue:w.value,"onUpdate:modelValue":r[0]||(r[0]=t=>w.value=t),errors:k.value},null,8,["action","blueprint","meta","modelValue","errors"]),l(o(P),{class:"overflow-hidden p-0"},{default:a(()=>[e("div",re,[l(o(H),{modelValue:y.value,"onUpdate:modelValue":r[1]||(r[1]=t=>y.value=t),placeholder:"Search"},null,8,["modelValue"])]),e("div",oe,[s.type=="redirects"?(c(),d("table",le,[r[4]||(r[4]=e("thead",null,[e("tr",null,[e("th",{class:"group from-column sortable-column",style:{width:"33%"}},[e("span",null,"From")]),e("th",{class:"group from-column sortable-column pr-8 w-24",style:{width:"33%"}},[e("span",null,"To")]),e("th",{class:"group to-column pr-8",style:{width:"8%"}},[e("span",null,"Type")]),e("th",{class:"group to-column pr-8",style:{width:"15%"}},[e("span",null,"Sites")]),e("th",{class:"actions-column",style:{width:"13.4%"}})])],-1)),e("tbody",null,[(c(!0),d(M,null,L(I.value,t=>(c(),d("tr",{key:t.id,style:{width:"100%",overflow:"clip"}},[e("td",null,i(t.from),1),e("td",null,i(t.to),1),e("td",null,i(t.redirect_type),1),e("td",null,i(t.sites&&t.sites.length?t.sites.join(", "):"Unknown"),1),e("td",null,[l(o(S),{icon:"trash",size:"sm",onClick:T=>B(t.from,t.id),text:"Remove",variant:"danger"},null,8,["onClick"])])]))),128))])])):s.type=="query-strings"?(c(),d("table",ne,[r[5]||(r[5]=e("thead",null,[e("tr",null,[e("th",{class:"group from-column sortable-column",style:{width:"46%"}},[e("span",null,"Query String Key")]),e("th",{class:"group to-column pr-8",style:{width:"20%"}},[e("span",null,"Strip")]),e("th",{class:"group to-column pr-8",style:{width:"20.6%"}},[e("span",null,"Sites")]),e("th",{class:"actions-column",style:{width:"13.4%"}})])],-1)),e("tbody",null,[(c(!0),d(M,null,L(I.value,(t,T)=>(c(),d("tr",{key:t.id,style:{width:"100%",overflow:"clip"}},[e("td",null,i(t.query_string),1),e("td",null,[l(o(Q),{modelValue:t.strip,"onUpdate:modelValue":[h=>t.strip=h,h=>q(t.query_string,"strip")]},null,8,["modelValue","onUpdate:modelValue"])]),e("td",null,i(t.sites&&t.sites.length?t.sites.join(", "):"Unknown"),1),e("td",null,[l(o(S),{icon:"trash",size:"sm",onClick:h=>z(t.query_string),text:"Remove",variant:"danger"},null,8,["onClick"])])]))),128))])])):G("",!0)]),l(o(K),{"resource-meta":{current_page:u.value,last_page:b.value,total:s.items.length},"show-totals":!1,"show-per-page-selector":!1,onPageSelected:g},null,8,["resource-meta"])]),_:1}),e("div",{class:N(["flex justify-between",{hidden:s.type=="query-strings"}])},[l(o(P),{class:"w-full xl:w-1/2 card overflow-hidden p-0 mb-4 mt-4 mr-4 px-4 py-4"},{default:a(()=>[e("header",null,[l(o(D),null,{default:a(()=>[...r[6]||(r[6]=[f("CSV Export",-1)])]),_:1}),l(o(F),null,{default:a(()=>[...r[7]||(r[7]=[f("Exports CSV of all redirects, use this format on import.",-1)])]),_:1})]),e("a",{class:"btn-primary",href:n.cp_url("/alt-design/alt-redirect/export"),download:""},[l(o(S),{text:"Export CSV"})],8,se)]),_:1}),l(o(P),{class:"w-full xl:w-1/2 card overflow-hidden p-0 mb-4 mt-4 ml-4 px-4 py-4"},{default:a(()=>[e("header",null,[l(o(D),null,{default:a(()=>[...r[8]||(r[8]=[f("CSV Import",-1)])]),_:1}),l(o(F),null,{default:a(()=>[...r[9]||(r[9]=[f("Import CSV for redirects, use the export format on import.",-1)])]),_:1})]),e("div",ae,[l(o(H),{type:"file",onInput:r[2]||(r[2]=t=>C.value=t.target.files[0])}),l(o(S),{onClick:r[3]||(r[3]=t=>U()),text:"Import"})])]),_:1})],2)]))}};Statamic.booting(()=>{Statamic.$inertia.register("alt-redirect::Index",ie)}); diff --git a/resources/dist/build/assets/alt-redirect-addon-d5a1e6a6.js b/resources/dist/build/assets/alt-redirect-addon-d5a1e6a6.js deleted file mode 100644 index c8ee705..0000000 --- a/resources/dist/build/assets/alt-redirect-addon-d5a1e6a6.js +++ /dev/null @@ -1 +0,0 @@ -function f(a,t,e,s,n,i,c,p){var r=typeof a=="function"?a.options:a;t&&(r.render=t,r.staticRenderFns=e,r._compiled=!0),s&&(r.functional=!0),i&&(r._scopeId="data-v-"+i);var o;if(c?(o=function(l){l=l||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,!l&&typeof __VUE_SSR_CONTEXT__<"u"&&(l=__VUE_SSR_CONTEXT__),n&&n.call(this,l),l&&l._registeredComponents&&l._registeredComponents.add(c)},r._ssrRegister=o):n&&(o=p?function(){n.call(this,(r.functional?this.parent:this).$root.$options.shadowRoot)}:n),o)if(r.functional){r._injectStyles=o;var h=r.render;r.render=function(m,u){return o.call(u),h(m,u)}}else{var d=r.beforeCreate;r.beforeCreate=d?[].concat(d,o):[o]}return{exports:a,options:r}}const g={props:{title:String,instructions:String,action:String,blueprint:Array,meta:Array,redirectTo:String,values:Array,data:Array,items:Array,type:String},computed:{lastPage(){return Math.ceil(this.totalItems/this.perPage)}},data(){return{itemsReady:[],itemsSliced:[],perPage:10,currentPage:1,totalItems:0,selectedFile:null,search:"",fileName:"Choose a file...",selectedPage:""}},watch:{search:{immediate:!0,handler(){this.sliceItems()}}},mounted(){this.itemsReady=this.items,this.totalItems=this.items.length,this.sliceItems()},methods:{updateItems(a){this.itemsReady=a.data.data,this.totalItems=a.data.data.length,this.sliceItems(),this.$forceUpdate()},setPage(a){this.currentPage=a,this.sliceItems()},sliceItems(){let a=this.itemsReady;this.search&&(a=a.filter(s=>Object.values(s).map(i=>i.toString().toLowerCase()).some(i=>i.includes(this.search.toLowerCase()))));const t=(this.currentPage-1)*this.perPage,e=t+this.perPage;this.totalItems=a.length,this.itemsSliced=a.slice(t,e)},deleteRedirect(a,t){confirm("Are you sure you want to delete this redirect?")&&Statamic.$axios.post(cp_url("alt-design/alt-redirect/delete"),{from:a,id:t}).then(e=>{this.updateItems(e)}).catch(e=>{console.log(e)})},deleteQueryString(a){confirm("Are you sure you want to delete this query string?")&&Statamic.$axios.post(cp_url("/alt-design/alt-redirect/query-strings/delete"),{query_string:a}).then(t=>{this.updateItems(t)}).catch(t=>{console.log(t)})},importFromCSV(){if(!this.selectedFile){alert("You haven't attached a CSV file!");return}var a=new FormData;a.append("file",this.selectedFile),a.append("data",JSON.stringify(this.itemsReady)),Statamic.$axios.post(cp_url("alt-design/alt-redirect/import"),a,{headers:{"Content-Type":"multipart/form-data"}}).then(t=>{location.reload()}).catch(t=>{console.log(t)})},handleFileUpload(a){this.selectedFile=a.target.files[0],this.fileName=this.selectedFile?this.selectedFile.name:"Choose a file..."},dropdownPageChange(){this.setPage(this.selectedPage)},toggleKey(a,t){Statamic.$axios.post(cp_url("/alt-design/alt-redirect/query-strings/toggle"),{index:a,toggleKey:t}).then(e=>{this.updateItems(e)}).catch(e=>{console.log(e)})}}};var _=function(){var t=this,e=t._self._c;return e("div",{attrs:{id:"alt-redirect"}},[e("h1",{staticClass:"flex-1"},[t._v(t._s(t.title))]),e("h2",{staticClass:"flex-1"},[t._v(t._s(t.instructions))]),e("publish-form",{attrs:{title:"",action:t.action,blueprint:t.blueprint,meta:t.meta,values:t.values},on:{saved:function(s){return t.updateItems(s)}}}),e("div",{staticClass:"card overflow-hidden p-0"},[e("div",{staticClass:"mt-4 pb-2 px-4"},[e("input",{directives:[{name:"model",rawName:"v-model",value:t.search,expression:"search"}],staticClass:"input-text",attrs:{type:"text",placeholder:"Search"},domProps:{value:t.search},on:{input:function(s){s.target.composing||(t.search=s.target.value)}}})]),e("div",{staticClass:"px-2"},[t.type=="redirects"?e("table",{staticClass:"data-table",staticStyle:{"table-layout":"fixed"},attrs:{"data-size":"sm",tabindex:"0"}},[t._m(0),e("tbody",t._l(t.itemsSliced,function(s){return e("tr",{key:s.id,staticStyle:{width:"100%",overflow:"clip"}},[e("td",[t._v(" "+t._s(s.from)+" ")]),e("td",[t._v(" "+t._s(s.to)+" ")]),e("td",[t._v(" "+t._s(s.redirect_type)+" ")]),e("td",[t._v(" "+t._s(s.sites&&s.sites.length?s.sites.join(", "):"Unknown")+" ")]),e("td",[e("button",{staticClass:"btn",staticStyle:{color:"#bc2626"},on:{click:function(n){return t.deleteRedirect(s.from,s.id)}}},[t._v("Remove ")])])])}),0)]):t._e(),t.type=="query-strings"?e("table",{staticClass:"data-table",staticStyle:{"table-layout":"fixed"},attrs:{"data-size":"sm",tabindex:"0"}},[t._m(1),e("tbody",t._l(t.itemsSliced,function(s,n){return e("tr",{key:s.id,staticStyle:{width:"100%",overflow:"clip"}},[e("td",[t._v(" "+t._s(s.query_string)+" ")]),e("td",[e("button",{staticClass:"toggle-container",class:{on:s.strip},attrs:{type:"button","aria-pressed":"false","aria-label":"Toggle Button",id:"field_preserve"},on:{click:function(i){return t.toggleKey(s.query_string,"strip")}}},[t._m(2,!0)])]),e("td",[t._v(" "+t._s(s.sites&&s.sites.length?s.sites.join(", "):"Unknown")+" ")]),e("td",[e("button",{staticClass:"btn",staticStyle:{color:"#bc2626"},on:{click:function(i){return t.deleteQueryString(s.query_string)}}},[t._v("Remove ")])])])}),0)]):t._e()]),e("div",{staticClass:"pagination text-sm py-4 px-4 flex items-center justify-between"},[e("div",{staticClass:"w-1/3 flex items-center"},[t._v(" Page "),e("span",{staticClass:"font-semibold mx-1",domProps:{innerHTML:t._s(t.currentPage)}}),t._v(" of "),e("span",{staticClass:"mx-1",domProps:{innerHTML:t._s(t.lastPage)}})]),e("div",{staticClass:"w-1/3 flex items-center justify-center"},[e("span",{staticClass:"cursor-pointer",staticStyle:{height:"15px",margin:"0 15px",width:"12px"},on:{click:function(s){return t.setPage(t.currentPage-1>0?t.currentPage-1:1)}}},[e("svg",{attrs:{xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",width:"205",height:"205",viewBox:"0 0 205 205"}},[e("defs",[e("clipPath",{attrs:{id:"clip-LEFT"}},[e("rect",{attrs:{width:"205",height:"205"}})])]),e("g",{attrs:{id:"LEFT","clip-path":"url(#clip-LEFT)"}},[e("rect",{attrs:{width:"205",height:"205",fill:"#fff"}}),e("path",{attrs:{stroke:"#2e9fff",fill:"#2e9fff",id:"Icon_awesome-arrow-left","data-name":"Icon awesome-arrow-left",d:"M114.961,184.524l-9.91,9.91a10.669,10.669,0,0,1-15.132,0L3.143,107.7a10.669,10.669,0,0,1,0-15.132L89.919,5.794a10.669,10.669,0,0,1,15.132,0l9.91,9.91a10.725,10.725,0,0,1-.179,15.311L60.994,82.259H189.283A10.687,10.687,0,0,1,200,92.972v14.284a10.687,10.687,0,0,1-10.713,10.713H60.994l53.789,51.244A10.648,10.648,0,0,1,114.961,184.524Z",transform:"translate(2.004 2.353)"}})])])]),t.currentPage>1?e("span",{staticClass:"cursor-pointer py-1 mx-1",on:{click:function(s){return t.setPage(1)}}},[t._v("1")]):t._e(),t.currentPage==1?e("span",{staticClass:"cursor-pointer py-1 mx-1 font-semibold",on:{click:function(s){return t.setPage(1)}}},[t._v("1")]):t._e(),t.currentPage>3?e("span",[t._v("...")]):t._e(),t.currentPage>2?e("span",{staticClass:"cursor-pointer py-1 mx-1",on:{click:function(s){return t.setPage(t.currentPage-1)}}},[t._v(t._s(t.currentPage-1))]):t._e(),t.currentPage!==1&&t.currentPage!==t.lastPage?e("span",{staticClass:"cursor-pointer py-1 mx-1 font-semibold"},[t._v(t._s(t.currentPage))]):t._e(),t.currentPage{Statamic.$components.register("alt-redirect",w)}); diff --git a/resources/dist/build/assets/alt-redirect-addon-tn0RQdqM.css b/resources/dist/build/assets/alt-redirect-addon-tn0RQdqM.css new file mode 100644 index 0000000..e69de29 diff --git a/resources/dist/build/manifest.json b/resources/dist/build/manifest.json index e3a4be2..de0760b 100644 --- a/resources/dist/build/manifest.json +++ b/resources/dist/build/manifest.json @@ -1,12 +1,17 @@ { "resources/css/alt-redirect-addon.css": { - "file": "assets/alt-redirect-addon-4ed993c7.js", + "file": "assets/alt-redirect-addon-tn0RQdqM.css", + "src": "resources/css/alt-redirect-addon.css", "isEntry": true, - "src": "resources/css/alt-redirect-addon.css" + "name": "alt-redirect-addon", + "names": [ + "alt-redirect-addon.css" + ] }, "resources/js/alt-redirect-addon.js": { - "file": "assets/alt-redirect-addon-d5a1e6a6.js", - "isEntry": true, - "src": "resources/js/alt-redirect-addon.js" + "file": "assets/alt-redirect-addon-Bj7zCgN-.js", + "name": "alt-redirect-addon", + "src": "resources/js/alt-redirect-addon.js", + "isEntry": true } } \ No newline at end of file diff --git a/resources/js/alt-redirect-addon.js b/resources/js/alt-redirect-addon.js index 94fa865..b4f2e73 100644 --- a/resources/js/alt-redirect-addon.js +++ b/resources/js/alt-redirect-addon.js @@ -1,5 +1,5 @@ import AltRedirect from './components/AltRedirect.vue'; Statamic.booting(() => { - Statamic.$components.register('alt-redirect', AltRedirect); + Statamic.$inertia.register('alt-redirect::Index', AltRedirect); }); diff --git a/resources/js/components/AltRedirect.vue b/resources/js/components/AltRedirect.vue index 68e2800..a89b840 100644 --- a/resources/js/components/AltRedirect.vue +++ b/resources/js/components/AltRedirect.vue @@ -1,151 +1,141 @@ - diff --git a/resources/views/index.blade.php b/resources/views/index.blade.php deleted file mode 100644 index 412df92..0000000 --- a/resources/views/index.blade.php +++ /dev/null @@ -1,20 +0,0 @@ -@extends('statamic::layout') - -@section('content') -
- - - -
- - -@endsection diff --git a/src/Http/Controllers/AltRedirectController.php b/src/Http/Controllers/AltRedirectController.php index 109b8f7..5eae0cd 100644 --- a/src/Http/Controllers/AltRedirectController.php +++ b/src/Http/Controllers/AltRedirectController.php @@ -4,6 +4,7 @@ use AltDesign\AltRedirect\Helpers\Data; use Illuminate\Http\Request; +use Inertia\Inertia; use Statamic\Fields\Blueprint; use Statamic\Fields\BlueprintRepository; use Statamic\Filesystem\Manager; @@ -28,8 +29,7 @@ class AltRedirectController // Work out what page we're handling public function __construct() { - $path = request()->path(); - if (str_contains($path, 'query-strings')) { + if(collect([request()->path(), request()->input('type')])->filter(fn($value) => !empty($value) && str_contains($value, 'query-strings'))->isNotEmpty()) { $this->type = 'query-strings'; } } @@ -58,11 +58,11 @@ public function index() Blueprint::setDirectory($oldDirectory); } - return view('alt-redirect::index', [ + return Inertia::render('alt-redirect::Index', [ 'blueprint' => $blueprint->toPublishArray(), - 'values' => $fields->values(), - 'meta' => $fields->meta(), - 'data' => $values, + 'initialValues' => $fields->values(), + 'initialMeta' => $fields->meta(), + 'items' => $values, 'type' => $this->type, 'action' => $this->actions[$this->type], 'title' => $this->titles[$this->type], @@ -128,9 +128,9 @@ public function delete(Request $request) $data = new Data($this->type); $values = $data->all(); - return [ + return redirect()->back()->with([ 'data' => $values, - ]; + ]); } // Import and Export can stay hardcoded to redirects since I/O for Query Strings aren't supported atm @@ -159,7 +159,9 @@ public function export(Request $request) public function import(Request $request) { - $currentData = json_decode($request->get('data'), true); + $data = new Data($this->type); + $currentData = $data->all(); + $file = $request->file('file'); $handle = fopen($file->path(), 'r'); if ($handle !== false) { @@ -220,8 +222,8 @@ public function toggle(Request $request) $data = new Data($this->type); $values = $data->all(); - return [ + return redirect()->back()->with([ 'data' => $values, - ]; + ]); } } diff --git a/vite.config.js b/vite.config.js index 687a5cc..62b2ae4 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,6 +1,6 @@ import { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin'; -import vue from '@vitejs/plugin-vue2'; +import statamic from '@statamic/cms/vite-plugin'; export default defineConfig({ plugins: [ @@ -11,6 +11,6 @@ export default defineConfig({ ], publicDirectory: 'resources/dist', }), - vue(), + statamic(), ], }); From c0e4939d13269467de19b35fde86204f56c2073f Mon Sep 17 00:00:00 2001 From: Alt-Charlie Date: Mon, 16 Feb 2026 15:39:58 +0000 Subject: [PATCH 04/29] Tweak assets --- package.json | 7 +++---- .../build/assets/alt-redirect-addon-Bj7zCgN-.js | 1 - .../assets/alt-redirect-addon-tn0RQdqM.css | 0 resources/dist/build/manifest.json | 17 ----------------- resources/js/components/AltRedirect.vue | 2 +- src/Http/Controllers/AltRedirectController.php | 4 ++-- 6 files changed, 6 insertions(+), 25 deletions(-) delete mode 100644 resources/dist/build/assets/alt-redirect-addon-Bj7zCgN-.js delete mode 100644 resources/dist/build/assets/alt-redirect-addon-tn0RQdqM.css delete mode 100644 resources/dist/build/manifest.json diff --git a/package.json b/package.json index 4f68882..900e75e 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,12 @@ { "private": true, + "type": "module", "scripts": { "dev": "vite", - "build": "vite build" - }, - "dependencies": { - "@statamic/cms": "file:./vendor/statamic/cms/resources/dist-package" + "build": "vite build --mode production" }, "devDependencies": { + "@statamic/cms": "file:./vendor/statamic/cms/resources/dist-package", "laravel-vite-plugin": "^2.0.1", "vite": "^7.3.1" } diff --git a/resources/dist/build/assets/alt-redirect-addon-Bj7zCgN-.js b/resources/dist/build/assets/alt-redirect-addon-Bj7zCgN-.js deleted file mode 100644 index 1cd3371..0000000 --- a/resources/dist/build/assets/alt-redirect-addon-Bj7zCgN-.js +++ /dev/null @@ -1 +0,0 @@ -const $=window.Vue,{BaseTransition:ue,BaseTransitionPropsValidators:de,Comment:ce,DeprecationTypes:pe,EffectScope:me,ErrorCodes:ge,ErrorTypeStrings:fe,Fragment:M,KeepAlive:Se,ReactiveEffect:ve,Static:ye,Suspense:he,Teleport:Ce,Text:we,TrackOpTypes:be,Transition:Te,TransitionGroup:xe,TriggerOpTypes:Pe,VueElement:Re,__esModule:ke,assertNumber:Ve,callWithAsyncErrorHandling:Ae,callWithErrorHandling:Ie,camelize:Me,capitalize:Ee,cloneVNode:Le,compatUtils:De,compile:He,computed:E,createApp:Fe,createBlock:_e,createCommentVNode:G,createElementBlock:d,createElementVNode:e,createHydrationRenderer:Be,createPropsRestProxy:ze,createRenderer:Ue,createSSRApp:qe,createSlots:Oe,createStaticVNode:$e,createTextVNode:f,createVNode:l,customRef:Ge,defineAsyncComponent:Ne,defineComponent:je,defineCustomElement:Ke,defineEmits:We,defineExpose:Qe,defineModel:Ye,defineOptions:Je,defineProps:Xe,defineSSRCustomElement:Ze,defineSlots:et,devtools:tt,effect:rt,effectScope:ot,getCurrentInstance:lt,getCurrentScope:nt,getCurrentWatcher:st,getTransitionRawChildren:at,guardReactiveProps:it,h:ut,handleError:dt,hasInjectionContext:ct,hydrate:pt,hydrateOnIdle:mt,hydrateOnInteraction:gt,hydrateOnMediaQuery:ft,hydrateOnVisible:St,initCustomFormatter:vt,initDirectivesForSSR:yt,inject:ht,isMemoSame:Ct,isProxy:wt,isReactive:bt,isReadonly:Tt,isRef:xt,isRuntimeOnly:Pt,isShallow:Rt,isVNode:kt,markRaw:Vt,mergeDefaults:At,mergeModels:It,mergeProps:Mt,nextTick:Et,nodeOps:Lt,normalizeClass:N,normalizeProps:Dt,normalizeStyle:Ht,onActivated:Ft,onBeforeMount:_t,onBeforeUnmount:Bt,onBeforeUpdate:zt,onDeactivated:Ut,onErrorCaptured:qt,onMounted:Ot,onRenderTracked:$t,onRenderTriggered:Gt,onScopeDispose:Nt,onServerPrefetch:jt,onUnmounted:Kt,onUpdated:Wt,onWatcherCleanup:Qt,openBlock:c,patchProp:Yt,popScopeId:Jt,provide:Xt,proxyRefs:Zt,pushScopeId:er,queuePostFlushCb:tr,reactive:rr,readonly:or,ref:p,registerRuntimeCompiler:lr,render:nr,renderList:L,renderSlot:sr,resolveComponent:ar,resolveDirective:ir,resolveDynamicComponent:ur,resolveFilter:dr,resolveTransitionHooks:cr,setBlockTracking:pr,setDevtoolsHook:mr,setTransitionHooks:gr,shallowReactive:fr,shallowReadonly:Sr,shallowRef:vr,ssrContextKey:yr,ssrUtils:hr,stop:Cr,toDisplayString:i,toHandlerKey:wr,toHandlers:br,toRaw:Tr,toRef:xr,toRefs:Pr,toValue:Rr,transformVNodeArgs:kr,triggerRef:Vr,unref:o,useAttrs:Ar,useCssModule:Ir,useCssVars:Mr,useHost:Er,useId:Lr,useModel:Dr,useSSRContext:Hr,useShadowRoot:Fr,useSlots:_r,useTemplateRef:Br,useTransitionState:zr,vModelCheckbox:Ur,vModelDynamic:qr,vModelRadio:Or,vModelSelect:$r,vModelText:Gr,vShow:Nr,version:jr,warn:Kr,watch:Wr,watchEffect:Qr,watchPostEffect:Yr,watchSyncEffect:Jr,withAsyncContext:Xr,withCtx:a,withDefaults:Zr,withDirectives:eo,withKeys:to,withMemo:ro,withModifiers:oo,withScopeId:lo}=$,{Alert:no,AuthCard:so,Avatar:ao,Badge:io,Button:S,ButtonGroup:uo,Calendar:co,Card:P,CardList:po,CardListItem:mo,CardPanel:go,CharacterCounter:fo,Checkbox:So,CheckboxGroup:vo,CodeEditor:yo,Combobox:ho,CommandPaletteItem:Co,ConfirmationModal:wo,Context:bo,ContextFooter:To,ContextHeader:xo,ContextItem:Po,ContextLabel:Ro,ContextMenu:ko,ContextSeparator:Vo,CreateForm:Ao,DatePicker:Io,DateRangePicker:Mo,Description:Eo,DocsCallout:Lo,DragHandle:Do,Dropdown:Ho,DropdownItem:Fo,DropdownLabel:_o,DropdownMenu:Bo,DropdownSeparator:zo,DropdownFooter:Uo,DropdownHeader:qo,Editable:Oo,ErrorMessage:$o,EmptyStateItem:Go,EmptyStateMenu:No,Field:jo,Header:j,Heading:D,HoverCard:Ko,Icon:Wo,Input:H,InputGroup:Qo,InputGroupAppend:Yo,InputGroupPrepend:Jo,Label:Xo,Listing:Zo,ListingCustomizeColumns:el,ListingFilters:tl,ListingHeaderCell:rl,ListingPagination:ol,ListingPresets:ll,ListingPresetTrigger:nl,ListingRowActions:sl,ListingSearch:al,ListingTable:il,ListingTableBody:ul,ListingTableHead:dl,ListingToggleAll:cl,LivePreview:pl,LivePreviewPopout:ml,Modal:gl,ModalClose:fl,ModalTitle:Sl,Pagination:K,Panel:vl,PanelFooter:yl,PanelHeader:hl,Popover:Cl,PublishComponents:wl,PublishContainer:W,publishContextKey:bl,injectPublishContext:Tl,PublishField:xl,PublishFields:Pl,PublishFieldsProvider:Rl,PublishForm:kl,PublishLocalizations:Vl,PublishSections:Al,PublishTabs:Il,Radio:Ml,RadioGroup:El,Select:Ll,Separator:Dl,Slider:Hl,Skeleton:Fl,SplitterGroup:_l,SplitterPanel:Bl,SplitterResizeHandle:zl,StatusIndicator:Ul,Subheading:F,Switch:Q,TabContent:ql,Stack:Ol,StackClose:$l,StackHeader:Gl,StackFooter:Nl,StackContent:jl,Table:Kl,TableCell:Wl,TableColumn:Ql,TableColumns:Yl,TableRow:Jl,TableRows:Xl,TabList:Zl,TabProvider:en,Tabs:tn,TabTrigger:rn,Textarea:on,TimePicker:ln,ToggleGroup:nn,ToggleItem:sn,Widget:an,registerIconSet:un,registerIconSetFromStrings:dn}=__STATAMIC__.ui,{AfterSaveHooks:Y,BeforeSaveHooks:J,Pipeline:X,PipelineStopped:cn,Request:Z}=__STATAMIC__.savePipeline,{Form:pn,Head:mn,Link:gn,router:v,toggleArchitecturalBackground:fn,useArchitecturalBackground:Sn,useForm:vn,usePoll:yn}=__STATAMIC__.inertia,ee={id:"alt-redirect"},te={class:"text-sm"},re={class:"my-4 pb-2 px-4"},oe={class:"px-2"},le={key:0,"data-size":"sm",tabindex:"0",class:"data-table",style:{"table-layout":"fixed"}},ne={key:1,"data-size":"sm",tabindex:"0",class:"data-table",style:{"table-layout":"fixed"}},se=["href"],ae={class:"flex justify-between items-center"},R=10,ie={__name:"AltRedirect",props:{title:String,instructions:String,action:String,blueprint:Array,initialMeta:Array,initialValues:Array,items:Array,type:String},setup(s){const m=s,u=p(1),C=p(null),y=p(""),w=p({...m.initialValues}),_=m.initialMeta,k=p({}),V=p(!1),A=p("container"),b=E(()=>Math.ceil(m.items.length/R)),I=E(()=>{let n=m.items;y.value?.length>0&&(n=n.filter(T=>Object.values(T).map(x=>x?.toString().toLowerCase()).some(x=>x?.includes(y.value.toLowerCase()))));const r=(u.value-1)*R,t=r+R;return n.slice(r,t)});function g(n){n>b.value&&(n=b.value),u.value=n}function B(n,r){confirm("Are you sure you want to delete this redirect?")&&v.post(cp_url("alt-design/alt-redirect/delete"),{from:n,id:r},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("Redirect deleted successfully!"),g(u.value)}})}function z(n){confirm("Are you sure you want to delete this query string?")&&v.post(cp_url("/alt-design/alt-redirect/query-strings/delete"),{query_string:n},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("Query string deleted successfully!"),g(u.value)}})}function U(){if(!C.value){alert("You haven't attached a CSV file!");return}v.post(cp_url("alt-design/alt-redirect/import"),{file:C.value},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("CSV imported successfully!"),g(u.value)}})}function q(n,r){v.post(cp_url("/alt-design/alt-redirect/query-strings/toggle"),{index:n,toggleKey:r},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("Toggled successfully!"),g(u.value)}})}function O(){new X().provide({container:A,errors:k,saving:V}).through([new J("alt-redirect"),new Z(cp_url("/alt-design/alt-redirect"),"POST",{type:m.type}),new Y("alt-redirect")]).then(()=>{w.value={...m.initialValues},Statamic.$toast.success("Redirect added successfully!"),v.reload()})}return(n,r)=>(c(),d("div",ee,[l(o(j),{title:s.title},{title:a(()=>[e("div",null,[f(i(s.title)+" ",1),e("div",te,i(s.instructions),1)])]),default:a(()=>[l(o(S),{text:"Save",variant:"primary",disabled:V.value,onClick:O},null,8,["disabled"])]),_:1},8,["title"]),l(o(W),{ref_key:"container",ref:A,action:s.action,blueprint:s.blueprint,meta:o(_),modelValue:w.value,"onUpdate:modelValue":r[0]||(r[0]=t=>w.value=t),errors:k.value},null,8,["action","blueprint","meta","modelValue","errors"]),l(o(P),{class:"overflow-hidden p-0"},{default:a(()=>[e("div",re,[l(o(H),{modelValue:y.value,"onUpdate:modelValue":r[1]||(r[1]=t=>y.value=t),placeholder:"Search"},null,8,["modelValue"])]),e("div",oe,[s.type=="redirects"?(c(),d("table",le,[r[4]||(r[4]=e("thead",null,[e("tr",null,[e("th",{class:"group from-column sortable-column",style:{width:"33%"}},[e("span",null,"From")]),e("th",{class:"group from-column sortable-column pr-8 w-24",style:{width:"33%"}},[e("span",null,"To")]),e("th",{class:"group to-column pr-8",style:{width:"8%"}},[e("span",null,"Type")]),e("th",{class:"group to-column pr-8",style:{width:"15%"}},[e("span",null,"Sites")]),e("th",{class:"actions-column",style:{width:"13.4%"}})])],-1)),e("tbody",null,[(c(!0),d(M,null,L(I.value,t=>(c(),d("tr",{key:t.id,style:{width:"100%",overflow:"clip"}},[e("td",null,i(t.from),1),e("td",null,i(t.to),1),e("td",null,i(t.redirect_type),1),e("td",null,i(t.sites&&t.sites.length?t.sites.join(", "):"Unknown"),1),e("td",null,[l(o(S),{icon:"trash",size:"sm",onClick:T=>B(t.from,t.id),text:"Remove",variant:"danger"},null,8,["onClick"])])]))),128))])])):s.type=="query-strings"?(c(),d("table",ne,[r[5]||(r[5]=e("thead",null,[e("tr",null,[e("th",{class:"group from-column sortable-column",style:{width:"46%"}},[e("span",null,"Query String Key")]),e("th",{class:"group to-column pr-8",style:{width:"20%"}},[e("span",null,"Strip")]),e("th",{class:"group to-column pr-8",style:{width:"20.6%"}},[e("span",null,"Sites")]),e("th",{class:"actions-column",style:{width:"13.4%"}})])],-1)),e("tbody",null,[(c(!0),d(M,null,L(I.value,(t,T)=>(c(),d("tr",{key:t.id,style:{width:"100%",overflow:"clip"}},[e("td",null,i(t.query_string),1),e("td",null,[l(o(Q),{modelValue:t.strip,"onUpdate:modelValue":[h=>t.strip=h,h=>q(t.query_string,"strip")]},null,8,["modelValue","onUpdate:modelValue"])]),e("td",null,i(t.sites&&t.sites.length?t.sites.join(", "):"Unknown"),1),e("td",null,[l(o(S),{icon:"trash",size:"sm",onClick:h=>z(t.query_string),text:"Remove",variant:"danger"},null,8,["onClick"])])]))),128))])])):G("",!0)]),l(o(K),{"resource-meta":{current_page:u.value,last_page:b.value,total:s.items.length},"show-totals":!1,"show-per-page-selector":!1,onPageSelected:g},null,8,["resource-meta"])]),_:1}),e("div",{class:N(["flex justify-between",{hidden:s.type=="query-strings"}])},[l(o(P),{class:"w-full xl:w-1/2 card overflow-hidden p-0 mb-4 mt-4 mr-4 px-4 py-4"},{default:a(()=>[e("header",null,[l(o(D),null,{default:a(()=>[...r[6]||(r[6]=[f("CSV Export",-1)])]),_:1}),l(o(F),null,{default:a(()=>[...r[7]||(r[7]=[f("Exports CSV of all redirects, use this format on import.",-1)])]),_:1})]),e("a",{class:"btn-primary",href:n.cp_url("/alt-design/alt-redirect/export"),download:""},[l(o(S),{text:"Export CSV"})],8,se)]),_:1}),l(o(P),{class:"w-full xl:w-1/2 card overflow-hidden p-0 mb-4 mt-4 ml-4 px-4 py-4"},{default:a(()=>[e("header",null,[l(o(D),null,{default:a(()=>[...r[8]||(r[8]=[f("CSV Import",-1)])]),_:1}),l(o(F),null,{default:a(()=>[...r[9]||(r[9]=[f("Import CSV for redirects, use the export format on import.",-1)])]),_:1})]),e("div",ae,[l(o(H),{type:"file",onInput:r[2]||(r[2]=t=>C.value=t.target.files[0])}),l(o(S),{onClick:r[3]||(r[3]=t=>U()),text:"Import"})])]),_:1})],2)]))}};Statamic.booting(()=>{Statamic.$inertia.register("alt-redirect::Index",ie)}); diff --git a/resources/dist/build/assets/alt-redirect-addon-tn0RQdqM.css b/resources/dist/build/assets/alt-redirect-addon-tn0RQdqM.css deleted file mode 100644 index e69de29..0000000 diff --git a/resources/dist/build/manifest.json b/resources/dist/build/manifest.json deleted file mode 100644 index de0760b..0000000 --- a/resources/dist/build/manifest.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "resources/css/alt-redirect-addon.css": { - "file": "assets/alt-redirect-addon-tn0RQdqM.css", - "src": "resources/css/alt-redirect-addon.css", - "isEntry": true, - "name": "alt-redirect-addon", - "names": [ - "alt-redirect-addon.css" - ] - }, - "resources/js/alt-redirect-addon.js": { - "file": "assets/alt-redirect-addon-Bj7zCgN-.js", - "name": "alt-redirect-addon", - "src": "resources/js/alt-redirect-addon.js", - "isEntry": true - } -} \ No newline at end of file diff --git a/resources/js/components/AltRedirect.vue b/resources/js/components/AltRedirect.vue index a89b840..e20c40b 100644 --- a/resources/js/components/AltRedirect.vue +++ b/resources/js/components/AltRedirect.vue @@ -20,7 +20,7 @@ const currentPage = ref(1); const selectedFile = ref(null); const search = ref(''); const values = ref({...props.initialValues}); -const meta = props.initialMeta; +const meta = ref(props.initialMeta); const errors = ref({}); const saving = ref(false); const container = ref('container'); diff --git a/src/Http/Controllers/AltRedirectController.php b/src/Http/Controllers/AltRedirectController.php index 5eae0cd..23c346b 100644 --- a/src/Http/Controllers/AltRedirectController.php +++ b/src/Http/Controllers/AltRedirectController.php @@ -60,8 +60,8 @@ public function index() return Inertia::render('alt-redirect::Index', [ 'blueprint' => $blueprint->toPublishArray(), - 'initialValues' => $fields->values(), - 'initialMeta' => $fields->meta(), + 'initialValues' => $fields->values()->all(), + 'initialMeta' => $fields->meta()->all(), 'items' => $values, 'type' => $this->type, 'action' => $this->actions[$this->type], From 97cfa2a2f835cdc6e15d2b4d611f586ffa36739a Mon Sep 17 00:00:00 2001 From: Alt-Charlie Date: Mon, 16 Feb 2026 15:42:11 +0000 Subject: [PATCH 05/29] Include prod assets --- .../build/assets/alt-redirect-addon-b6lPb8Q2.js | 1 + .../assets/alt-redirect-addon-tn0RQdqM.css | 0 resources/dist/build/manifest.json | 17 +++++++++++++++++ 3 files changed, 18 insertions(+) create mode 100644 resources/dist/build/assets/alt-redirect-addon-b6lPb8Q2.js create mode 100644 resources/dist/build/assets/alt-redirect-addon-tn0RQdqM.css create mode 100644 resources/dist/build/manifest.json diff --git a/resources/dist/build/assets/alt-redirect-addon-b6lPb8Q2.js b/resources/dist/build/assets/alt-redirect-addon-b6lPb8Q2.js new file mode 100644 index 0000000..b14f260 --- /dev/null +++ b/resources/dist/build/assets/alt-redirect-addon-b6lPb8Q2.js @@ -0,0 +1 @@ +const $=window.Vue,{BaseTransition:ue,BaseTransitionPropsValidators:de,Comment:ce,DeprecationTypes:pe,EffectScope:me,ErrorCodes:ge,ErrorTypeStrings:fe,Fragment:M,KeepAlive:Se,ReactiveEffect:ve,Static:ye,Suspense:he,Teleport:Ce,Text:we,TrackOpTypes:be,Transition:Te,TransitionGroup:xe,TriggerOpTypes:Pe,VueElement:Re,__esModule:ke,assertNumber:Ve,callWithAsyncErrorHandling:Ae,callWithErrorHandling:Ie,camelize:Me,capitalize:Ee,cloneVNode:Le,compatUtils:De,compile:He,computed:E,createApp:Fe,createBlock:_e,createCommentVNode:G,createElementBlock:c,createElementVNode:e,createHydrationRenderer:Be,createPropsRestProxy:ze,createRenderer:Ue,createSSRApp:qe,createSlots:Oe,createStaticVNode:$e,createTextVNode:f,createVNode:o,customRef:Ge,defineAsyncComponent:Ne,defineComponent:je,defineCustomElement:Ke,defineEmits:We,defineExpose:Qe,defineModel:Ye,defineOptions:Je,defineProps:Xe,defineSSRCustomElement:Ze,defineSlots:et,devtools:tt,effect:rt,effectScope:ot,getCurrentInstance:lt,getCurrentScope:nt,getCurrentWatcher:st,getTransitionRawChildren:at,guardReactiveProps:it,h:ut,handleError:dt,hasInjectionContext:ct,hydrate:pt,hydrateOnIdle:mt,hydrateOnInteraction:gt,hydrateOnMediaQuery:ft,hydrateOnVisible:St,initCustomFormatter:vt,initDirectivesForSSR:yt,inject:ht,isMemoSame:Ct,isProxy:wt,isReactive:bt,isReadonly:Tt,isRef:xt,isRuntimeOnly:Pt,isShallow:Rt,isVNode:kt,markRaw:Vt,mergeDefaults:At,mergeModels:It,mergeProps:Mt,nextTick:Et,nodeOps:Lt,normalizeClass:N,normalizeProps:Dt,normalizeStyle:Ht,onActivated:Ft,onBeforeMount:_t,onBeforeUnmount:Bt,onBeforeUpdate:zt,onDeactivated:Ut,onErrorCaptured:qt,onMounted:Ot,onRenderTracked:$t,onRenderTriggered:Gt,onScopeDispose:Nt,onServerPrefetch:jt,onUnmounted:Kt,onUpdated:Wt,onWatcherCleanup:Qt,openBlock:p,patchProp:Yt,popScopeId:Jt,provide:Xt,proxyRefs:Zt,pushScopeId:er,queuePostFlushCb:tr,reactive:rr,readonly:or,ref:i,registerRuntimeCompiler:lr,render:nr,renderList:L,renderSlot:sr,resolveComponent:ar,resolveDirective:ir,resolveDynamicComponent:ur,resolveFilter:dr,resolveTransitionHooks:cr,setBlockTracking:pr,setDevtoolsHook:mr,setTransitionHooks:gr,shallowReactive:fr,shallowReadonly:Sr,shallowRef:vr,ssrContextKey:yr,ssrUtils:hr,stop:Cr,toDisplayString:u,toHandlerKey:wr,toHandlers:br,toRaw:Tr,toRef:xr,toRefs:Pr,toValue:Rr,transformVNodeArgs:kr,triggerRef:Vr,unref:l,useAttrs:Ar,useCssModule:Ir,useCssVars:Mr,useHost:Er,useId:Lr,useModel:Dr,useSSRContext:Hr,useShadowRoot:Fr,useSlots:_r,useTemplateRef:Br,useTransitionState:zr,vModelCheckbox:Ur,vModelDynamic:qr,vModelRadio:Or,vModelSelect:$r,vModelText:Gr,vShow:Nr,version:jr,warn:Kr,watch:Wr,watchEffect:Qr,watchPostEffect:Yr,watchSyncEffect:Jr,withAsyncContext:Xr,withCtx:a,withDefaults:Zr,withDirectives:eo,withKeys:to,withMemo:ro,withModifiers:oo,withScopeId:lo}=$,{Alert:no,AuthCard:so,Avatar:ao,Badge:io,Button:S,ButtonGroup:uo,Calendar:co,Card:P,CardList:po,CardListItem:mo,CardPanel:go,CharacterCounter:fo,Checkbox:So,CheckboxGroup:vo,CodeEditor:yo,Combobox:ho,CommandPaletteItem:Co,ConfirmationModal:wo,Context:bo,ContextFooter:To,ContextHeader:xo,ContextItem:Po,ContextLabel:Ro,ContextMenu:ko,ContextSeparator:Vo,CreateForm:Ao,DatePicker:Io,DateRangePicker:Mo,Description:Eo,DocsCallout:Lo,DragHandle:Do,Dropdown:Ho,DropdownItem:Fo,DropdownLabel:_o,DropdownMenu:Bo,DropdownSeparator:zo,DropdownFooter:Uo,DropdownHeader:qo,Editable:Oo,ErrorMessage:$o,EmptyStateItem:Go,EmptyStateMenu:No,Field:jo,Header:j,Heading:D,HoverCard:Ko,Icon:Wo,Input:H,InputGroup:Qo,InputGroupAppend:Yo,InputGroupPrepend:Jo,Label:Xo,Listing:Zo,ListingCustomizeColumns:el,ListingFilters:tl,ListingHeaderCell:rl,ListingPagination:ol,ListingPresets:ll,ListingPresetTrigger:nl,ListingRowActions:sl,ListingSearch:al,ListingTable:il,ListingTableBody:ul,ListingTableHead:dl,ListingToggleAll:cl,LivePreview:pl,LivePreviewPopout:ml,Modal:gl,ModalClose:fl,ModalTitle:Sl,Pagination:K,Panel:vl,PanelFooter:yl,PanelHeader:hl,Popover:Cl,PublishComponents:wl,PublishContainer:W,publishContextKey:bl,injectPublishContext:Tl,PublishField:xl,PublishFields:Pl,PublishFieldsProvider:Rl,PublishForm:kl,PublishLocalizations:Vl,PublishSections:Al,PublishTabs:Il,Radio:Ml,RadioGroup:El,Select:Ll,Separator:Dl,Slider:Hl,Skeleton:Fl,SplitterGroup:_l,SplitterPanel:Bl,SplitterResizeHandle:zl,StatusIndicator:Ul,Subheading:F,Switch:Q,TabContent:ql,Stack:Ol,StackClose:$l,StackHeader:Gl,StackFooter:Nl,StackContent:jl,Table:Kl,TableCell:Wl,TableColumn:Ql,TableColumns:Yl,TableRow:Jl,TableRows:Xl,TabList:Zl,TabProvider:en,Tabs:tn,TabTrigger:rn,Textarea:on,TimePicker:ln,ToggleGroup:nn,ToggleItem:sn,Widget:an,registerIconSet:un,registerIconSetFromStrings:dn}=__STATAMIC__.ui,{AfterSaveHooks:Y,BeforeSaveHooks:J,Pipeline:X,PipelineStopped:cn,Request:Z}=__STATAMIC__.savePipeline,{Form:pn,Head:mn,Link:gn,router:v,toggleArchitecturalBackground:fn,useArchitecturalBackground:Sn,useForm:vn,usePoll:yn}=__STATAMIC__.inertia,ee={id:"alt-redirect"},te={class:"text-sm"},re={class:"my-4 pb-2 px-4"},oe={class:"px-2"},le={key:0,"data-size":"sm",tabindex:"0",class:"data-table",style:{"table-layout":"fixed"}},ne={key:1,"data-size":"sm",tabindex:"0",class:"data-table",style:{"table-layout":"fixed"}},se=["href"],ae={class:"flex justify-between items-center"},R=10,ie={__name:"AltRedirect",props:{title:String,instructions:String,action:String,blueprint:Array,initialMeta:Array,initialValues:Array,items:Array,type:String},setup(s){const m=s,d=i(1),C=i(null),y=i(""),w=i({...m.initialValues}),_=i(m.initialMeta),k=i({}),V=i(!1),A=i("container"),b=E(()=>Math.ceil(m.items.length/R)),I=E(()=>{let n=m.items;y.value?.length>0&&(n=n.filter(T=>Object.values(T).map(x=>x?.toString().toLowerCase()).some(x=>x?.includes(y.value.toLowerCase()))));const r=(d.value-1)*R,t=r+R;return n.slice(r,t)});function g(n){n>b.value&&(n=b.value),d.value=n}function B(n,r){confirm("Are you sure you want to delete this redirect?")&&v.post(cp_url("alt-design/alt-redirect/delete"),{from:n,id:r},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("Redirect deleted successfully!"),g(d.value)}})}function z(n){confirm("Are you sure you want to delete this query string?")&&v.post(cp_url("/alt-design/alt-redirect/query-strings/delete"),{query_string:n},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("Query string deleted successfully!"),g(d.value)}})}function U(){if(!C.value){alert("You haven't attached a CSV file!");return}v.post(cp_url("alt-design/alt-redirect/import"),{file:C.value},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("CSV imported successfully!"),g(d.value)}})}function q(n,r){v.post(cp_url("/alt-design/alt-redirect/query-strings/toggle"),{index:n,toggleKey:r},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("Toggled successfully!"),g(d.value)}})}function O(){new X().provide({container:A,errors:k,saving:V}).through([new J("alt-redirect"),new Z(cp_url("/alt-design/alt-redirect"),"POST",{type:m.type}),new Y("alt-redirect")]).then(()=>{w.value={...m.initialValues},Statamic.$toast.success("Redirect added successfully!"),v.reload()})}return(n,r)=>(p(),c("div",ee,[o(l(j),{title:s.title},{title:a(()=>[e("div",null,[f(u(s.title)+" ",1),e("div",te,u(s.instructions),1)])]),default:a(()=>[o(l(S),{text:"Save",variant:"primary",disabled:V.value,onClick:O},null,8,["disabled"])]),_:1},8,["title"]),o(l(W),{ref_key:"container",ref:A,action:s.action,blueprint:s.blueprint,meta:_.value,modelValue:w.value,"onUpdate:modelValue":r[0]||(r[0]=t=>w.value=t),errors:k.value},null,8,["action","blueprint","meta","modelValue","errors"]),o(l(P),{class:"overflow-hidden p-0"},{default:a(()=>[e("div",re,[o(l(H),{modelValue:y.value,"onUpdate:modelValue":r[1]||(r[1]=t=>y.value=t),placeholder:"Search"},null,8,["modelValue"])]),e("div",oe,[s.type=="redirects"?(p(),c("table",le,[r[4]||(r[4]=e("thead",null,[e("tr",null,[e("th",{class:"group from-column sortable-column",style:{width:"33%"}},[e("span",null,"From")]),e("th",{class:"group from-column sortable-column pr-8 w-24",style:{width:"33%"}},[e("span",null,"To")]),e("th",{class:"group to-column pr-8",style:{width:"8%"}},[e("span",null,"Type")]),e("th",{class:"group to-column pr-8",style:{width:"15%"}},[e("span",null,"Sites")]),e("th",{class:"actions-column",style:{width:"13.4%"}})])],-1)),e("tbody",null,[(p(!0),c(M,null,L(I.value,t=>(p(),c("tr",{key:t.id,style:{width:"100%",overflow:"clip"}},[e("td",null,u(t.from),1),e("td",null,u(t.to),1),e("td",null,u(t.redirect_type),1),e("td",null,u(t.sites&&t.sites.length?t.sites.join(", "):"Unknown"),1),e("td",null,[o(l(S),{icon:"trash",size:"sm",onClick:T=>B(t.from,t.id),text:"Remove",variant:"danger"},null,8,["onClick"])])]))),128))])])):s.type=="query-strings"?(p(),c("table",ne,[r[5]||(r[5]=e("thead",null,[e("tr",null,[e("th",{class:"group from-column sortable-column",style:{width:"46%"}},[e("span",null,"Query String Key")]),e("th",{class:"group to-column pr-8",style:{width:"20%"}},[e("span",null,"Strip")]),e("th",{class:"group to-column pr-8",style:{width:"20.6%"}},[e("span",null,"Sites")]),e("th",{class:"actions-column",style:{width:"13.4%"}})])],-1)),e("tbody",null,[(p(!0),c(M,null,L(I.value,(t,T)=>(p(),c("tr",{key:t.id,style:{width:"100%",overflow:"clip"}},[e("td",null,u(t.query_string),1),e("td",null,[o(l(Q),{modelValue:t.strip,"onUpdate:modelValue":[h=>t.strip=h,h=>q(t.query_string,"strip")]},null,8,["modelValue","onUpdate:modelValue"])]),e("td",null,u(t.sites&&t.sites.length?t.sites.join(", "):"Unknown"),1),e("td",null,[o(l(S),{icon:"trash",size:"sm",onClick:h=>z(t.query_string),text:"Remove",variant:"danger"},null,8,["onClick"])])]))),128))])])):G("",!0)]),o(l(K),{"resource-meta":{current_page:d.value,last_page:b.value,total:s.items.length},"show-totals":!1,"show-per-page-selector":!1,onPageSelected:g},null,8,["resource-meta"])]),_:1}),e("div",{class:N(["flex justify-between",{hidden:s.type=="query-strings"}])},[o(l(P),{class:"w-full xl:w-1/2 card overflow-hidden p-0 mb-4 mt-4 mr-4 px-4 py-4"},{default:a(()=>[e("header",null,[o(l(D),null,{default:a(()=>[...r[6]||(r[6]=[f("CSV Export",-1)])]),_:1}),o(l(F),null,{default:a(()=>[...r[7]||(r[7]=[f("Exports CSV of all redirects, use this format on import.",-1)])]),_:1})]),e("a",{class:"btn-primary",href:n.cp_url("/alt-design/alt-redirect/export"),download:""},[o(l(S),{text:"Export CSV"})],8,se)]),_:1}),o(l(P),{class:"w-full xl:w-1/2 card overflow-hidden p-0 mb-4 mt-4 ml-4 px-4 py-4"},{default:a(()=>[e("header",null,[o(l(D),null,{default:a(()=>[...r[8]||(r[8]=[f("CSV Import",-1)])]),_:1}),o(l(F),null,{default:a(()=>[...r[9]||(r[9]=[f("Import CSV for redirects, use the export format on import.",-1)])]),_:1})]),e("div",ae,[o(l(H),{type:"file",onInput:r[2]||(r[2]=t=>C.value=t.target.files[0])}),o(l(S),{onClick:r[3]||(r[3]=t=>U()),text:"Import"})])]),_:1})],2)]))}};Statamic.booting(()=>{Statamic.$inertia.register("alt-redirect::Index",ie)}); diff --git a/resources/dist/build/assets/alt-redirect-addon-tn0RQdqM.css b/resources/dist/build/assets/alt-redirect-addon-tn0RQdqM.css new file mode 100644 index 0000000..e69de29 diff --git a/resources/dist/build/manifest.json b/resources/dist/build/manifest.json new file mode 100644 index 0000000..eb40319 --- /dev/null +++ b/resources/dist/build/manifest.json @@ -0,0 +1,17 @@ +{ + "resources/css/alt-redirect-addon.css": { + "file": "assets/alt-redirect-addon-tn0RQdqM.css", + "src": "resources/css/alt-redirect-addon.css", + "isEntry": true, + "name": "alt-redirect-addon", + "names": [ + "alt-redirect-addon.css" + ] + }, + "resources/js/alt-redirect-addon.js": { + "file": "assets/alt-redirect-addon-b6lPb8Q2.js", + "name": "alt-redirect-addon", + "src": "resources/js/alt-redirect-addon.js", + "isEntry": true + } +} \ No newline at end of file From dd48ca0a664c4c2a78aceaacf47648b4f74e6e5d Mon Sep 17 00:00:00 2001 From: Alt-Charlie Date: Mon, 16 Feb 2026 16:10:04 +0000 Subject: [PATCH 06/29] Added return --- src/Http/Controllers/AltRedirectController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Http/Controllers/AltRedirectController.php b/src/Http/Controllers/AltRedirectController.php index 23c346b..61651c0 100644 --- a/src/Http/Controllers/AltRedirectController.php +++ b/src/Http/Controllers/AltRedirectController.php @@ -194,6 +194,7 @@ public function import(Request $request) $data = new Data('redirects'); $data->saveAll($currentData); + return true; } // Toggle a key in a certain item and return the data afterwards From 909932c833ce229642cc7f663460152158925ce7 Mon Sep 17 00:00:00 2001 From: Alt-Charlie Date: Mon, 16 Feb 2026 16:17:19 +0000 Subject: [PATCH 07/29] Remedials --- .../assets/alt-redirect-addon-Y5Y_fYKX.js | 1 + .../assets/alt-redirect-addon-b6lPb8Q2.js | 1 - resources/dist/build/manifest.json | 2 +- resources/js/components/AltRedirect.vue | 19 +++++++++++++------ 4 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 resources/dist/build/assets/alt-redirect-addon-Y5Y_fYKX.js delete mode 100644 resources/dist/build/assets/alt-redirect-addon-b6lPb8Q2.js diff --git a/resources/dist/build/assets/alt-redirect-addon-Y5Y_fYKX.js b/resources/dist/build/assets/alt-redirect-addon-Y5Y_fYKX.js new file mode 100644 index 0000000..3c8ba3a --- /dev/null +++ b/resources/dist/build/assets/alt-redirect-addon-Y5Y_fYKX.js @@ -0,0 +1 @@ +const $=window.Vue,{BaseTransition:de,BaseTransitionPropsValidators:ce,Comment:pe,DeprecationTypes:me,EffectScope:ge,ErrorCodes:fe,ErrorTypeStrings:Se,Fragment:M,KeepAlive:ve,ReactiveEffect:ye,Static:he,Suspense:Ce,Teleport:we,Text:be,TrackOpTypes:Te,Transition:xe,TransitionGroup:Pe,TriggerOpTypes:Re,VueElement:ke,__esModule:Ve,assertNumber:Ae,callWithAsyncErrorHandling:Ie,callWithErrorHandling:Me,camelize:Ee,capitalize:Le,cloneVNode:De,compatUtils:He,compile:Fe,computed:E,createApp:_e,createBlock:Be,createCommentVNode:G,createElementBlock:c,createElementVNode:e,createHydrationRenderer:ze,createPropsRestProxy:Ue,createRenderer:qe,createSSRApp:Oe,createSlots:$e,createStaticVNode:Ge,createTextVNode:S,createVNode:o,customRef:Ne,defineAsyncComponent:je,defineComponent:Ke,defineCustomElement:We,defineEmits:Qe,defineExpose:Ye,defineModel:Je,defineOptions:Xe,defineProps:Ze,defineSSRCustomElement:et,defineSlots:tt,devtools:rt,effect:ot,effectScope:lt,getCurrentInstance:nt,getCurrentScope:st,getCurrentWatcher:at,getTransitionRawChildren:it,guardReactiveProps:ut,h:dt,handleError:ct,hasInjectionContext:pt,hydrate:mt,hydrateOnIdle:gt,hydrateOnInteraction:ft,hydrateOnMediaQuery:St,hydrateOnVisible:vt,initCustomFormatter:yt,initDirectivesForSSR:ht,inject:Ct,isMemoSame:wt,isProxy:bt,isReactive:Tt,isReadonly:xt,isRef:Pt,isRuntimeOnly:Rt,isShallow:kt,isVNode:Vt,markRaw:At,mergeDefaults:It,mergeModels:Mt,mergeProps:Et,nextTick:Lt,nodeOps:Dt,normalizeClass:N,normalizeProps:Ht,normalizeStyle:Ft,onActivated:_t,onBeforeMount:Bt,onBeforeUnmount:zt,onBeforeUpdate:Ut,onDeactivated:qt,onErrorCaptured:Ot,onMounted:$t,onRenderTracked:Gt,onRenderTriggered:Nt,onScopeDispose:jt,onServerPrefetch:Kt,onUnmounted:Wt,onUpdated:Qt,onWatcherCleanup:Yt,openBlock:p,patchProp:Jt,popScopeId:Xt,provide:Zt,proxyRefs:er,pushScopeId:tr,queuePostFlushCb:rr,reactive:or,readonly:lr,ref:i,registerRuntimeCompiler:nr,render:sr,renderList:L,renderSlot:ar,resolveComponent:ir,resolveDirective:ur,resolveDynamicComponent:dr,resolveFilter:cr,resolveTransitionHooks:pr,setBlockTracking:mr,setDevtoolsHook:gr,setTransitionHooks:fr,shallowReactive:Sr,shallowReadonly:vr,shallowRef:yr,ssrContextKey:hr,ssrUtils:Cr,stop:wr,toDisplayString:u,toHandlerKey:br,toHandlers:Tr,toRaw:xr,toRef:Pr,toRefs:Rr,toValue:kr,transformVNodeArgs:Vr,triggerRef:Ar,unref:l,useAttrs:Ir,useCssModule:Mr,useCssVars:Er,useHost:Lr,useId:Dr,useModel:Hr,useSSRContext:Fr,useShadowRoot:_r,useSlots:Br,useTemplateRef:zr,useTransitionState:Ur,vModelCheckbox:qr,vModelDynamic:Or,vModelRadio:$r,vModelSelect:Gr,vModelText:Nr,vShow:jr,version:Kr,warn:Wr,watch:j,watchEffect:Qr,watchPostEffect:Yr,watchSyncEffect:Jr,withAsyncContext:Xr,withCtx:a,withDefaults:Zr,withDirectives:eo,withKeys:to,withMemo:ro,withModifiers:oo,withScopeId:lo}=$,{Alert:no,AuthCard:so,Avatar:ao,Badge:io,Button:v,ButtonGroup:uo,Calendar:co,Card:R,CardList:po,CardListItem:mo,CardPanel:go,CharacterCounter:fo,Checkbox:So,CheckboxGroup:vo,CodeEditor:yo,Combobox:ho,CommandPaletteItem:Co,ConfirmationModal:wo,Context:bo,ContextFooter:To,ContextHeader:xo,ContextItem:Po,ContextLabel:Ro,ContextMenu:ko,ContextSeparator:Vo,CreateForm:Ao,DatePicker:Io,DateRangePicker:Mo,Description:Eo,DocsCallout:Lo,DragHandle:Do,Dropdown:Ho,DropdownItem:Fo,DropdownLabel:_o,DropdownMenu:Bo,DropdownSeparator:zo,DropdownFooter:Uo,DropdownHeader:qo,Editable:Oo,ErrorMessage:$o,EmptyStateItem:Go,EmptyStateMenu:No,Field:jo,Header:K,Heading:D,HoverCard:Ko,Icon:Wo,Input:H,InputGroup:Qo,InputGroupAppend:Yo,InputGroupPrepend:Jo,Label:Xo,Listing:Zo,ListingCustomizeColumns:el,ListingFilters:tl,ListingHeaderCell:rl,ListingPagination:ol,ListingPresets:ll,ListingPresetTrigger:nl,ListingRowActions:sl,ListingSearch:al,ListingTable:il,ListingTableBody:ul,ListingTableHead:dl,ListingToggleAll:cl,LivePreview:pl,LivePreviewPopout:ml,Modal:gl,ModalClose:fl,ModalTitle:Sl,Pagination:W,Panel:vl,PanelFooter:yl,PanelHeader:hl,Popover:Cl,PublishComponents:wl,PublishContainer:Q,publishContextKey:bl,injectPublishContext:Tl,PublishField:xl,PublishFields:Pl,PublishFieldsProvider:Rl,PublishForm:kl,PublishLocalizations:Vl,PublishSections:Al,PublishTabs:Il,Radio:Ml,RadioGroup:El,Select:Ll,Separator:Dl,Slider:Hl,Skeleton:Fl,SplitterGroup:_l,SplitterPanel:Bl,SplitterResizeHandle:zl,StatusIndicator:Ul,Subheading:F,Switch:Y,TabContent:ql,Stack:Ol,StackClose:$l,StackHeader:Gl,StackFooter:Nl,StackContent:jl,Table:Kl,TableCell:Wl,TableColumn:Ql,TableColumns:Yl,TableRow:Jl,TableRows:Xl,TabList:Zl,TabProvider:en,Tabs:tn,TabTrigger:rn,Textarea:on,TimePicker:ln,ToggleGroup:nn,ToggleItem:sn,Widget:an,registerIconSet:un,registerIconSetFromStrings:dn}=__STATAMIC__.ui,{AfterSaveHooks:J,BeforeSaveHooks:X,Pipeline:Z,PipelineStopped:cn,Request:ee}=__STATAMIC__.savePipeline,{Form:pn,Head:mn,Link:gn,router:y,toggleArchitecturalBackground:fn,useArchitecturalBackground:Sn,useForm:vn,usePoll:yn}=__STATAMIC__.inertia,te={id:"alt-redirect"},re={class:"text-sm"},oe={class:"my-4 pb-2 px-4"},le={class:"px-2"},ne={key:0,"data-size":"sm",tabindex:"0",class:"data-table",style:{"table-layout":"fixed"}},se={key:1,"data-size":"sm",tabindex:"0",class:"data-table",style:{"table-layout":"fixed"}},ae=["href"],ie={class:"flex justify-between items-center"},k=10,ue={__name:"AltRedirect",props:{title:String,instructions:String,action:String,blueprint:Array,initialMeta:Array,initialValues:Array,items:Array,type:String},setup(s){const g=s,d=i(1),w=i(null),f=i(""),b=i({...g.initialValues}),_=i(g.initialMeta),V=i({}),A=i(!1),I=i("container"),T=E(()=>Math.ceil(h.value.total/k)),h=E(()=>{let n=g.items;f.value?.length>0&&(n=n.filter(x=>Object.values(x).map(P=>P?.toString().toLowerCase()).some(P=>P?.includes(f.value.toLowerCase()))));const r=(d.value-1)*k,t=r+k;return{total:n.length,data:n.slice(r,t)}});function m(n){n>T.value&&(n=T.value),d.value=n}function B(n,r){confirm("Are you sure you want to delete this redirect?")&&y.post(cp_url("alt-design/alt-redirect/delete"),{from:n,id:r},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("Redirect deleted successfully!"),m(d.value)}})}function z(n){confirm("Are you sure you want to delete this query string?")&&y.post(cp_url("/alt-design/alt-redirect/query-strings/delete"),{query_string:n},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("Query string deleted successfully!"),m(d.value)}})}function U(){if(!w.value){alert("You haven't attached a CSV file!");return}y.post(cp_url("alt-design/alt-redirect/import"),{file:w.value},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("CSV imported successfully!"),m(d.value)}})}function q(n,r){y.post(cp_url("/alt-design/alt-redirect/query-strings/toggle"),{index:n,toggleKey:r},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("Toggled successfully!"),m(d.value)}})}function O(){new Z().provide({container:I,errors:V,saving:A}).through([new X("alt-redirect"),new ee(cp_url("/alt-design/alt-redirect"),"POST",{type:g.type}),new J("alt-redirect")]).then(()=>{b.value={...g.initialValues},Statamic.$toast.success("Redirect added successfully!"),y.reload()})}return j(f,()=>{m(1)}),(n,r)=>(p(),c("div",te,[o(l(K),{title:s.title},{title:a(()=>[e("div",null,[S(u(s.title)+" ",1),e("div",re,u(s.instructions),1)])]),default:a(()=>[o(l(v),{text:"Save",variant:"primary",disabled:A.value,onClick:O},null,8,["disabled"])]),_:1},8,["title"]),o(l(Q),{ref_key:"container",ref:I,action:s.action,blueprint:s.blueprint,meta:_.value,modelValue:b.value,"onUpdate:modelValue":r[0]||(r[0]=t=>b.value=t),errors:V.value},null,8,["action","blueprint","meta","modelValue","errors"]),o(l(R),{class:"overflow-hidden p-0"},{default:a(()=>[e("div",oe,[o(l(H),{modelValue:f.value,"onUpdate:modelValue":r[1]||(r[1]=t=>f.value=t),placeholder:"Search"},null,8,["modelValue"])]),e("div",le,[s.type=="redirects"?(p(),c("table",ne,[r[4]||(r[4]=e("thead",null,[e("tr",null,[e("th",{class:"group from-column sortable-column",style:{width:"33%"}},[e("span",null,"From")]),e("th",{class:"group from-column sortable-column pr-8 w-24",style:{width:"33%"}},[e("span",null,"To")]),e("th",{class:"group to-column pr-8",style:{width:"8%"}},[e("span",null,"Type")]),e("th",{class:"group to-column pr-8",style:{width:"15%"}},[e("span",null,"Sites")]),e("th",{class:"actions-column",style:{width:"13.4%"}})])],-1)),e("tbody",null,[(p(!0),c(M,null,L(h.value.data,t=>(p(),c("tr",{key:t.id,style:{width:"100%",overflow:"clip"}},[e("td",null,u(t.from),1),e("td",null,u(t.to),1),e("td",null,u(t.redirect_type),1),e("td",null,u(t.sites&&t.sites.length?t.sites.join(", "):"Unknown"),1),e("td",null,[o(l(v),{icon:"trash",size:"sm",onClick:x=>B(t.from,t.id),text:"Remove",variant:"danger"},null,8,["onClick"])])]))),128))])])):s.type=="query-strings"?(p(),c("table",se,[r[5]||(r[5]=e("thead",null,[e("tr",null,[e("th",{class:"group from-column sortable-column",style:{width:"46%"}},[e("span",null,"Query String Key")]),e("th",{class:"group to-column pr-8",style:{width:"20%"}},[e("span",null,"Strip")]),e("th",{class:"group to-column pr-8",style:{width:"20.6%"}},[e("span",null,"Sites")]),e("th",{class:"actions-column",style:{width:"13.4%"}})])],-1)),e("tbody",null,[(p(!0),c(M,null,L(h.value.data,(t,x)=>(p(),c("tr",{key:t.id,style:{width:"100%",overflow:"clip"}},[e("td",null,u(t.query_string),1),e("td",null,[o(l(Y),{modelValue:t.strip,"onUpdate:modelValue":[C=>t.strip=C,C=>q(t.query_string,"strip")]},null,8,["modelValue","onUpdate:modelValue"])]),e("td",null,u(t.sites&&t.sites.length?t.sites.join(", "):"Unknown"),1),e("td",null,[o(l(v),{icon:"trash",size:"sm",onClick:C=>z(t.query_string),text:"Remove",variant:"danger"},null,8,["onClick"])])]))),128))])])):G("",!0)]),o(l(W),{"resource-meta":{current_page:d.value,last_page:T.value,total:h.value.total},"show-totals":!1,"show-per-page-selector":!1,onPageSelected:m},null,8,["resource-meta"])]),_:1}),e("div",{class:N(["flex justify-between",{hidden:s.type=="query-strings"}])},[o(l(R),{class:"w-full xl:w-1/2 card overflow-hidden p-0 mb-4 mt-4 mr-4 px-4 py-4"},{default:a(()=>[e("header",null,[o(l(D),null,{default:a(()=>[...r[6]||(r[6]=[S("CSV Export",-1)])]),_:1}),o(l(F),null,{default:a(()=>[...r[7]||(r[7]=[S("Exports CSV of all redirects, use this format on import.",-1)])]),_:1})]),e("a",{class:"btn-primary",href:n.cp_url("/alt-design/alt-redirect/export"),download:""},[o(l(v),{text:"Export CSV"})],8,ae)]),_:1}),o(l(R),{class:"w-full xl:w-1/2 card overflow-hidden p-0 mb-4 mt-4 ml-4 px-4 py-4"},{default:a(()=>[e("header",null,[o(l(D),null,{default:a(()=>[...r[8]||(r[8]=[S("CSV Import",-1)])]),_:1}),o(l(F),null,{default:a(()=>[...r[9]||(r[9]=[S("Import CSV for redirects, use the export format on import.",-1)])]),_:1})]),e("div",ie,[o(l(H),{type:"file",onInput:r[2]||(r[2]=t=>w.value=t.target.files[0])}),o(l(v),{onClick:r[3]||(r[3]=t=>U()),text:"Import"})])]),_:1})],2)]))}};Statamic.booting(()=>{Statamic.$inertia.register("alt-redirect::Index",ue)}); diff --git a/resources/dist/build/assets/alt-redirect-addon-b6lPb8Q2.js b/resources/dist/build/assets/alt-redirect-addon-b6lPb8Q2.js deleted file mode 100644 index b14f260..0000000 --- a/resources/dist/build/assets/alt-redirect-addon-b6lPb8Q2.js +++ /dev/null @@ -1 +0,0 @@ -const $=window.Vue,{BaseTransition:ue,BaseTransitionPropsValidators:de,Comment:ce,DeprecationTypes:pe,EffectScope:me,ErrorCodes:ge,ErrorTypeStrings:fe,Fragment:M,KeepAlive:Se,ReactiveEffect:ve,Static:ye,Suspense:he,Teleport:Ce,Text:we,TrackOpTypes:be,Transition:Te,TransitionGroup:xe,TriggerOpTypes:Pe,VueElement:Re,__esModule:ke,assertNumber:Ve,callWithAsyncErrorHandling:Ae,callWithErrorHandling:Ie,camelize:Me,capitalize:Ee,cloneVNode:Le,compatUtils:De,compile:He,computed:E,createApp:Fe,createBlock:_e,createCommentVNode:G,createElementBlock:c,createElementVNode:e,createHydrationRenderer:Be,createPropsRestProxy:ze,createRenderer:Ue,createSSRApp:qe,createSlots:Oe,createStaticVNode:$e,createTextVNode:f,createVNode:o,customRef:Ge,defineAsyncComponent:Ne,defineComponent:je,defineCustomElement:Ke,defineEmits:We,defineExpose:Qe,defineModel:Ye,defineOptions:Je,defineProps:Xe,defineSSRCustomElement:Ze,defineSlots:et,devtools:tt,effect:rt,effectScope:ot,getCurrentInstance:lt,getCurrentScope:nt,getCurrentWatcher:st,getTransitionRawChildren:at,guardReactiveProps:it,h:ut,handleError:dt,hasInjectionContext:ct,hydrate:pt,hydrateOnIdle:mt,hydrateOnInteraction:gt,hydrateOnMediaQuery:ft,hydrateOnVisible:St,initCustomFormatter:vt,initDirectivesForSSR:yt,inject:ht,isMemoSame:Ct,isProxy:wt,isReactive:bt,isReadonly:Tt,isRef:xt,isRuntimeOnly:Pt,isShallow:Rt,isVNode:kt,markRaw:Vt,mergeDefaults:At,mergeModels:It,mergeProps:Mt,nextTick:Et,nodeOps:Lt,normalizeClass:N,normalizeProps:Dt,normalizeStyle:Ht,onActivated:Ft,onBeforeMount:_t,onBeforeUnmount:Bt,onBeforeUpdate:zt,onDeactivated:Ut,onErrorCaptured:qt,onMounted:Ot,onRenderTracked:$t,onRenderTriggered:Gt,onScopeDispose:Nt,onServerPrefetch:jt,onUnmounted:Kt,onUpdated:Wt,onWatcherCleanup:Qt,openBlock:p,patchProp:Yt,popScopeId:Jt,provide:Xt,proxyRefs:Zt,pushScopeId:er,queuePostFlushCb:tr,reactive:rr,readonly:or,ref:i,registerRuntimeCompiler:lr,render:nr,renderList:L,renderSlot:sr,resolveComponent:ar,resolveDirective:ir,resolveDynamicComponent:ur,resolveFilter:dr,resolveTransitionHooks:cr,setBlockTracking:pr,setDevtoolsHook:mr,setTransitionHooks:gr,shallowReactive:fr,shallowReadonly:Sr,shallowRef:vr,ssrContextKey:yr,ssrUtils:hr,stop:Cr,toDisplayString:u,toHandlerKey:wr,toHandlers:br,toRaw:Tr,toRef:xr,toRefs:Pr,toValue:Rr,transformVNodeArgs:kr,triggerRef:Vr,unref:l,useAttrs:Ar,useCssModule:Ir,useCssVars:Mr,useHost:Er,useId:Lr,useModel:Dr,useSSRContext:Hr,useShadowRoot:Fr,useSlots:_r,useTemplateRef:Br,useTransitionState:zr,vModelCheckbox:Ur,vModelDynamic:qr,vModelRadio:Or,vModelSelect:$r,vModelText:Gr,vShow:Nr,version:jr,warn:Kr,watch:Wr,watchEffect:Qr,watchPostEffect:Yr,watchSyncEffect:Jr,withAsyncContext:Xr,withCtx:a,withDefaults:Zr,withDirectives:eo,withKeys:to,withMemo:ro,withModifiers:oo,withScopeId:lo}=$,{Alert:no,AuthCard:so,Avatar:ao,Badge:io,Button:S,ButtonGroup:uo,Calendar:co,Card:P,CardList:po,CardListItem:mo,CardPanel:go,CharacterCounter:fo,Checkbox:So,CheckboxGroup:vo,CodeEditor:yo,Combobox:ho,CommandPaletteItem:Co,ConfirmationModal:wo,Context:bo,ContextFooter:To,ContextHeader:xo,ContextItem:Po,ContextLabel:Ro,ContextMenu:ko,ContextSeparator:Vo,CreateForm:Ao,DatePicker:Io,DateRangePicker:Mo,Description:Eo,DocsCallout:Lo,DragHandle:Do,Dropdown:Ho,DropdownItem:Fo,DropdownLabel:_o,DropdownMenu:Bo,DropdownSeparator:zo,DropdownFooter:Uo,DropdownHeader:qo,Editable:Oo,ErrorMessage:$o,EmptyStateItem:Go,EmptyStateMenu:No,Field:jo,Header:j,Heading:D,HoverCard:Ko,Icon:Wo,Input:H,InputGroup:Qo,InputGroupAppend:Yo,InputGroupPrepend:Jo,Label:Xo,Listing:Zo,ListingCustomizeColumns:el,ListingFilters:tl,ListingHeaderCell:rl,ListingPagination:ol,ListingPresets:ll,ListingPresetTrigger:nl,ListingRowActions:sl,ListingSearch:al,ListingTable:il,ListingTableBody:ul,ListingTableHead:dl,ListingToggleAll:cl,LivePreview:pl,LivePreviewPopout:ml,Modal:gl,ModalClose:fl,ModalTitle:Sl,Pagination:K,Panel:vl,PanelFooter:yl,PanelHeader:hl,Popover:Cl,PublishComponents:wl,PublishContainer:W,publishContextKey:bl,injectPublishContext:Tl,PublishField:xl,PublishFields:Pl,PublishFieldsProvider:Rl,PublishForm:kl,PublishLocalizations:Vl,PublishSections:Al,PublishTabs:Il,Radio:Ml,RadioGroup:El,Select:Ll,Separator:Dl,Slider:Hl,Skeleton:Fl,SplitterGroup:_l,SplitterPanel:Bl,SplitterResizeHandle:zl,StatusIndicator:Ul,Subheading:F,Switch:Q,TabContent:ql,Stack:Ol,StackClose:$l,StackHeader:Gl,StackFooter:Nl,StackContent:jl,Table:Kl,TableCell:Wl,TableColumn:Ql,TableColumns:Yl,TableRow:Jl,TableRows:Xl,TabList:Zl,TabProvider:en,Tabs:tn,TabTrigger:rn,Textarea:on,TimePicker:ln,ToggleGroup:nn,ToggleItem:sn,Widget:an,registerIconSet:un,registerIconSetFromStrings:dn}=__STATAMIC__.ui,{AfterSaveHooks:Y,BeforeSaveHooks:J,Pipeline:X,PipelineStopped:cn,Request:Z}=__STATAMIC__.savePipeline,{Form:pn,Head:mn,Link:gn,router:v,toggleArchitecturalBackground:fn,useArchitecturalBackground:Sn,useForm:vn,usePoll:yn}=__STATAMIC__.inertia,ee={id:"alt-redirect"},te={class:"text-sm"},re={class:"my-4 pb-2 px-4"},oe={class:"px-2"},le={key:0,"data-size":"sm",tabindex:"0",class:"data-table",style:{"table-layout":"fixed"}},ne={key:1,"data-size":"sm",tabindex:"0",class:"data-table",style:{"table-layout":"fixed"}},se=["href"],ae={class:"flex justify-between items-center"},R=10,ie={__name:"AltRedirect",props:{title:String,instructions:String,action:String,blueprint:Array,initialMeta:Array,initialValues:Array,items:Array,type:String},setup(s){const m=s,d=i(1),C=i(null),y=i(""),w=i({...m.initialValues}),_=i(m.initialMeta),k=i({}),V=i(!1),A=i("container"),b=E(()=>Math.ceil(m.items.length/R)),I=E(()=>{let n=m.items;y.value?.length>0&&(n=n.filter(T=>Object.values(T).map(x=>x?.toString().toLowerCase()).some(x=>x?.includes(y.value.toLowerCase()))));const r=(d.value-1)*R,t=r+R;return n.slice(r,t)});function g(n){n>b.value&&(n=b.value),d.value=n}function B(n,r){confirm("Are you sure you want to delete this redirect?")&&v.post(cp_url("alt-design/alt-redirect/delete"),{from:n,id:r},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("Redirect deleted successfully!"),g(d.value)}})}function z(n){confirm("Are you sure you want to delete this query string?")&&v.post(cp_url("/alt-design/alt-redirect/query-strings/delete"),{query_string:n},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("Query string deleted successfully!"),g(d.value)}})}function U(){if(!C.value){alert("You haven't attached a CSV file!");return}v.post(cp_url("alt-design/alt-redirect/import"),{file:C.value},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("CSV imported successfully!"),g(d.value)}})}function q(n,r){v.post(cp_url("/alt-design/alt-redirect/query-strings/toggle"),{index:n,toggleKey:r},{preserveState:!0,preserveScroll:!0,onSuccess:()=>{Statamic.$toast.success("Toggled successfully!"),g(d.value)}})}function O(){new X().provide({container:A,errors:k,saving:V}).through([new J("alt-redirect"),new Z(cp_url("/alt-design/alt-redirect"),"POST",{type:m.type}),new Y("alt-redirect")]).then(()=>{w.value={...m.initialValues},Statamic.$toast.success("Redirect added successfully!"),v.reload()})}return(n,r)=>(p(),c("div",ee,[o(l(j),{title:s.title},{title:a(()=>[e("div",null,[f(u(s.title)+" ",1),e("div",te,u(s.instructions),1)])]),default:a(()=>[o(l(S),{text:"Save",variant:"primary",disabled:V.value,onClick:O},null,8,["disabled"])]),_:1},8,["title"]),o(l(W),{ref_key:"container",ref:A,action:s.action,blueprint:s.blueprint,meta:_.value,modelValue:w.value,"onUpdate:modelValue":r[0]||(r[0]=t=>w.value=t),errors:k.value},null,8,["action","blueprint","meta","modelValue","errors"]),o(l(P),{class:"overflow-hidden p-0"},{default:a(()=>[e("div",re,[o(l(H),{modelValue:y.value,"onUpdate:modelValue":r[1]||(r[1]=t=>y.value=t),placeholder:"Search"},null,8,["modelValue"])]),e("div",oe,[s.type=="redirects"?(p(),c("table",le,[r[4]||(r[4]=e("thead",null,[e("tr",null,[e("th",{class:"group from-column sortable-column",style:{width:"33%"}},[e("span",null,"From")]),e("th",{class:"group from-column sortable-column pr-8 w-24",style:{width:"33%"}},[e("span",null,"To")]),e("th",{class:"group to-column pr-8",style:{width:"8%"}},[e("span",null,"Type")]),e("th",{class:"group to-column pr-8",style:{width:"15%"}},[e("span",null,"Sites")]),e("th",{class:"actions-column",style:{width:"13.4%"}})])],-1)),e("tbody",null,[(p(!0),c(M,null,L(I.value,t=>(p(),c("tr",{key:t.id,style:{width:"100%",overflow:"clip"}},[e("td",null,u(t.from),1),e("td",null,u(t.to),1),e("td",null,u(t.redirect_type),1),e("td",null,u(t.sites&&t.sites.length?t.sites.join(", "):"Unknown"),1),e("td",null,[o(l(S),{icon:"trash",size:"sm",onClick:T=>B(t.from,t.id),text:"Remove",variant:"danger"},null,8,["onClick"])])]))),128))])])):s.type=="query-strings"?(p(),c("table",ne,[r[5]||(r[5]=e("thead",null,[e("tr",null,[e("th",{class:"group from-column sortable-column",style:{width:"46%"}},[e("span",null,"Query String Key")]),e("th",{class:"group to-column pr-8",style:{width:"20%"}},[e("span",null,"Strip")]),e("th",{class:"group to-column pr-8",style:{width:"20.6%"}},[e("span",null,"Sites")]),e("th",{class:"actions-column",style:{width:"13.4%"}})])],-1)),e("tbody",null,[(p(!0),c(M,null,L(I.value,(t,T)=>(p(),c("tr",{key:t.id,style:{width:"100%",overflow:"clip"}},[e("td",null,u(t.query_string),1),e("td",null,[o(l(Q),{modelValue:t.strip,"onUpdate:modelValue":[h=>t.strip=h,h=>q(t.query_string,"strip")]},null,8,["modelValue","onUpdate:modelValue"])]),e("td",null,u(t.sites&&t.sites.length?t.sites.join(", "):"Unknown"),1),e("td",null,[o(l(S),{icon:"trash",size:"sm",onClick:h=>z(t.query_string),text:"Remove",variant:"danger"},null,8,["onClick"])])]))),128))])])):G("",!0)]),o(l(K),{"resource-meta":{current_page:d.value,last_page:b.value,total:s.items.length},"show-totals":!1,"show-per-page-selector":!1,onPageSelected:g},null,8,["resource-meta"])]),_:1}),e("div",{class:N(["flex justify-between",{hidden:s.type=="query-strings"}])},[o(l(P),{class:"w-full xl:w-1/2 card overflow-hidden p-0 mb-4 mt-4 mr-4 px-4 py-4"},{default:a(()=>[e("header",null,[o(l(D),null,{default:a(()=>[...r[6]||(r[6]=[f("CSV Export",-1)])]),_:1}),o(l(F),null,{default:a(()=>[...r[7]||(r[7]=[f("Exports CSV of all redirects, use this format on import.",-1)])]),_:1})]),e("a",{class:"btn-primary",href:n.cp_url("/alt-design/alt-redirect/export"),download:""},[o(l(S),{text:"Export CSV"})],8,se)]),_:1}),o(l(P),{class:"w-full xl:w-1/2 card overflow-hidden p-0 mb-4 mt-4 ml-4 px-4 py-4"},{default:a(()=>[e("header",null,[o(l(D),null,{default:a(()=>[...r[8]||(r[8]=[f("CSV Import",-1)])]),_:1}),o(l(F),null,{default:a(()=>[...r[9]||(r[9]=[f("Import CSV for redirects, use the export format on import.",-1)])]),_:1})]),e("div",ae,[o(l(H),{type:"file",onInput:r[2]||(r[2]=t=>C.value=t.target.files[0])}),o(l(S),{onClick:r[3]||(r[3]=t=>U()),text:"Import"})])]),_:1})],2)]))}};Statamic.booting(()=>{Statamic.$inertia.register("alt-redirect::Index",ie)}); diff --git a/resources/dist/build/manifest.json b/resources/dist/build/manifest.json index eb40319..f5cdd14 100644 --- a/resources/dist/build/manifest.json +++ b/resources/dist/build/manifest.json @@ -9,7 +9,7 @@ ] }, "resources/js/alt-redirect-addon.js": { - "file": "assets/alt-redirect-addon-b6lPb8Q2.js", + "file": "assets/alt-redirect-addon-Y5Y_fYKX.js", "name": "alt-redirect-addon", "src": "resources/js/alt-redirect-addon.js", "isEntry": true diff --git a/resources/js/components/AltRedirect.vue b/resources/js/components/AltRedirect.vue index e20c40b..0247a9b 100644 --- a/resources/js/components/AltRedirect.vue +++ b/resources/js/components/AltRedirect.vue @@ -2,7 +2,7 @@ import { Header, Heading, Subheading, PublishContainer, Button, Switch, Card, Input, Pagination } from '@statamic/cms/ui'; import { Pipeline, BeforeSaveHooks, Request, AfterSaveHooks } from '@statamic/cms/save-pipeline'; import { router } from '@statamic/cms/inertia' -import { computed, ref } from 'vue'; +import { computed, ref, watch } from 'vue'; const props = defineProps({ title: String, @@ -26,7 +26,7 @@ const saving = ref(false); const container = ref('container'); const lastPage = computed(() => { - return Math.ceil(props.items.length / perPage); + return Math.ceil(itemsSliced.value.total / perPage); }); const itemsSliced = computed(() => { @@ -44,7 +44,10 @@ const itemsSliced = computed(() => { const start = (currentPage.value - 1) * perPage; const end = start + perPage; - return temp.slice(start, end); + return { + total: temp.length, + data: temp.slice(start, end) + }; }); function setPage(page) { @@ -117,6 +120,10 @@ function save() { }); } +watch(search, () => { + setPage(1) +}); +