@sanity/document-internationalization 2.0.0-studio-v3-plugin-v2.1 → 2.0.0-studio-v3-plugin-v2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,14 +1,14 @@
1
+ # @sanity/document-internationalization
2
+
1
3
  - This is a completely new, **Sanity Studio v3 exclusive version** of @sanity/document-internationalization released as v2.0.0 which contains new features and requires content migrations to upgrade from previous versions. There is example code below.
2
4
 
3
5
  - For the **Studio v3 compatible version** of the original plugin, please install v1.0.0 and above.
4
6
 
5
7
  - For the **Studio v2 version** (plugin version 0), please refer to the [v2-branch](https://github.com/sanity-io/document-internationalization) and install v0.0.0 and above.
6
8
 
7
- # @sanity/document-internationalization
8
-
9
- ![v3 Studio with @sanity/document-internationalization v1 Installed](/img/v3-studio-with-doc-intl-v1.png)
9
+ ![v3 Studio with @sanity/document-internationalization v1 Installed](/img/sanity-document-internationalization-v2.png)
10
10
 
11
- A complete rewrite of the original Document Internationalization plugin, exclusively for Sanity Studio v3. Major benefits from the previous versions include:
11
+ A complete rewrite of the original Document Internationalization plugin, exclusively for Sanity Studio v3. Major **benefits** from the previous versions include:
12
12
 
13
13
  - Create new documents in any language and link references later
14
14
  - Translation references are written to a separate "meta" document
@@ -18,6 +18,14 @@ A complete rewrite of the original Document Internationalization plugin, exclusi
18
18
  - Configurable "language" field on documents
19
19
  - Built-in static and parameterized initial value templates for new documents
20
20
 
21
+ ## Note on Document counts
22
+
23
+ In previous versions of this plugin, translations were stored as an array of references on the actual documents. This required a base language and lead to messy transaction histories.
24
+
25
+ In this version of the plugin, translations of a document are stored as an array of references in a document of the `_type: translation.metadata`, and one is created for every document that has translations. A document with no translations will not have a metadata document.
26
+
27
+ This means if you have 100 documents and they are all translated into 3 languages, you will have 400 documents. Keep this in mind for extremely high-volume datasets.
28
+
21
29
  ## Install
22
30
 
23
31
  ```
@@ -53,6 +61,7 @@ export const createConfig({
53
61
  schemaTypes: ['lesson'],
54
62
  // Optional
55
63
  languageField: `language` // defauts to "language"
64
+ // Requires access to the Publishing API
56
65
  bulkPublish: true // defaults to false
57
66
  })
58
67
  ]
@@ -96,7 +105,7 @@ To query a single document and all its translations, we use the `references()` f
96
105
 
97
106
  ## Querying with GraphQL
98
107
 
99
- Fortunately the Sanity GraphQL API contains a similar filter for document references.
108
+ Fortunately, the Sanity GraphQL API contains a similar filter for document references.
100
109
 
101
110
  ```graphql
102
111
  # In this example we retrieve a lesson by its `slug.current` field value
@@ -129,7 +138,7 @@ query GetTranslations($id: ID!) {
129
138
 
130
139
  ## Migrating from v0 / v1
131
140
 
132
- There are two scripts in the `./migrations` folder of this repository. They contain scripts which should help move your content over – however they may require updating to match your current settings.
141
+ There are two scripts in the `./migrations` folder of this repository. They contain scripts that should help move your content over – however, they may require updating to match your current settings.
133
142
 
134
143
  **These have not been thoroughly tested on all platforms. Please take a backup before proceeding. Test on a duplicate dataset.**
135
144
 
@@ -138,7 +147,11 @@ There are two scripts in the `./migrations` folder of this repository. They cont
138
147
 
139
148
  ## Roadmap
140
149
 
141
- The major missing feature at this time is asynchronously loading languages. There may be others.
150
+ - [ ] Asynchronous language plugin config option
151
+ - [ ] Export a validator to allow the same slug on connected translations
152
+ - [ ] Guidance to copy/paste changes between documents
153
+ - [ ] Guidance on handling singletons
154
+ - [ ] Add extra fields to the metadata document
142
155
 
143
156
  ## License
144
157
 
package/lib/index.esm.js CHANGED
@@ -1,2 +1,2 @@
1
- function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function t(t){for(var a=1;a<arguments.length;a++){var r=null!=arguments[a]?arguments[a]:{};a%2?e(Object(r),!0).forEach((function(e){n(t,e,r[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):e(Object(r)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(r,e))}))}return t}function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}import{jsx as a,jsxs as r,Fragment as i}from"react/jsx-runtime";import{defineType as l,defineField as o,useClient as s,useEditState as c,useValidationStatus as d,useSchema as u,SanityPreview as p,useWorkspace as m,definePlugin as h}from"sanity";import{internationalizedArray as g}from"sanity-plugin-internationalized-array";import{useToast as f,Button as y,Flex as v,Spinner as b,Text as T,Box as _,Badge as I,useClickOutside as k,Card as O,Stack as j,Popover as P}from"@sanity/ui";import{TranslateIcon as S,SplitVerticalIcon as w,CheckmarkIcon as x,AddIcon as C,CogIcon as D,ChevronRightIcon as F}from"@sanity/icons";import z,{useCallback as E,useState as L}from"react";import{uuid as B}from"@sanity/uuid";import{usePaneRouter as M}from"sanity/desk";import{RouterContext as $}from"sanity/router";import{useListeningQuery as U}from"sanity-plugin-utils";var A=e=>l({type:"document",name:"translation.metadata",title:"Translation metadata",icon:S,liveEdit:!0,fields:[o({name:"translations",type:"internationalizedArrayReference"}),o({name:"schemaTypes",description:"Used to filter the reference fields above so all translations share the same types.",type:"array",of:[{type:"string"}],options:{list:e},readOnly:e=>{let{value:t}=e;return Boolean(t)}})],preview:{select:{translations:"translations",documentSchemaTypes:"schemaTypes"},prepare(e){const{translations:t,documentSchemaTypes:n}=e,a=1===t.length?"1 Translation":"".concat(t.length," Translations"),r=t.length?t.map((e=>e._key.toUpperCase())).join(", "):"";return{title:a,subtitle:[r?"(".concat(r,")"):null,(null==n?void 0:n.length)?n.map((e=>e.toUpperCase())).join(", "):"No Schemas Defined"].filter(Boolean).join(" ")}}}});function N(e,t){const n=z.useContext($),{routerPanesState:a,groupIndex:r}=M();return z.useCallback((()=>{if(!n||!e||!t)return;const i=[...a];i.splice(r+1,0,[{id:e,params:{type:t}}]);const l=n.resolvePathFromState({panes:i});n.navigateUrl({path:l})}),[e,t,n,a,r])}function q(e,t,n){return{_key:e,value:{_type:"reference",_ref:t,_weak:!0,_strengthenOnPublish:{type:n}}}}function R(e){var n;const{index:i,language:l,languageField:o,schemaType:c,documentId:d,disabled:u,current:p,sourceId:m,sourceLanguageId:h,metadata:g,translation:k}=e,O=s(),j=f(),P=N(null==(n=null==k?void 0:k.value)?void 0:n._ref,c),S=E((()=>P()),[P]),D=E((async()=>{var e;const n=Boolean(null==g?void 0:g._id),a=O.transaction(),r=d.startsWith("drafts.")?[d,d.replace("drafts.","")]:[d,"drafts.".concat(d)],s=t(t({},await O.fetch("*[_id in $ids]|order(_updatedAt desc)[0]",{ids:r})),{},{_id:"drafts.".concat(B()),[o]:l.id});a.create(s);const u=null!=(e=null==g?void 0:g._id)?e:B(),p=q(l.id,s._id.replace("drafts.",""),c);if(n){const e="translations[".concat(i-1,"]"),t=O.patch(u).setIfMissing({translations:[]}).insert("before",e,[p]);a.patch(t)}else{const e=h?q(h,m,c):null;a.createIfNotExists({_id:u,_type:"translation.metadata",schemaTypes:[c],translations:[p,e].filter(Boolean)})}a.commit().then((()=>j.push({status:"success",title:"Created ".concat(l.title," translation"),description:n?"Updated Translations Metadata":"Created Translations Metadata"}))).catch((e=>(console.error(e),j.push({status:"error",title:"Error creating translation",description:e.message}))))}),[O,d,i,l,o,null==g?void 0:g._id,c,m,h,j]);return a(y,{onClick:k?S:D,mode:p?"default":"bleed",disabled:u||p,children:r(v,{gap:3,align:"center",children:[u?a(b,{}):a(T,{size:2,children:a(k?w:p?x:C,{})}),a(_,{flex:1,children:a(T,{children:l.title})}),a(I,{tone:u||p?"default":"primary",children:l.id})]})})}function V(e){const{id:t}=e,n=N(t,"translation.metadata");return a(y,{disabled:!t,mode:"ghost",text:"Manage Translations",icon:D,onClick:()=>n()})}function W(e){const{language:t,languageField:n,documentId:r,schemaType:i,source:l,disabled:o=!1}=e,c=s(),d=f(),u=z.useCallback((()=>{const e=l?l._id:"draft.".concat(r),a=c.transaction();l||a.createIfNotExists({_id:e,_type:i});const o=c.patch(e).set({[n]:t.id});a.patch(o),a.commit().then((()=>{d.push({title:"Set document language to ".concat(t.title),status:"success"})})).catch((e=>(console.error(e),d.push({title:"Failed to set document language to ".concat(t.title),status:"error"}))))}),[l,r,c,n,t,i,d]);return a(y,{mode:"ghost",text:t.title,icon:F,onClick:()=>u(),disabled:o,justify:"flex-start"})}function G(e){const{supportedLanguages:t,schemaType:n,documentId:l,languageField:o}=e,[s,d]=L(!1),u=E((()=>d((e=>!e))),[]),[p,m]=L(null),[h,g]=L(null),f=E((()=>d(!1)),[]);k(f,[p,h]);const{data:v,loading:b,error:I}=function(e,t){const{data:n,loading:a,error:r}=U("*[_type == $translationSchema && $id in translations[].value._ref][0]",{params:{id:e,translationSchema:"translation.metadata"}});return{data:n,loading:a,error:r}}(l),{draft:w,published:x}=c(l,n),C=w||x,D=null==C?void 0:C[o],F=t.some((e=>e.id===D)),z=a(_,{overflow:"auto",children:I?a(O,{tone:"critical",padding:2,children:r(T,{children:["Error: ",I]})}):r(j,{padding:1,space:1,children:[t.length>0?r(i,{children:[t.map(((e,t)=>{var r;return!b&&D&&F?a(R,{index:t,language:e,languageField:o,schemaType:n,documentId:l,disabled:b,current:e.id===D,metadata:v,sourceId:l,sourceLanguageId:D,translation:null==v?void 0:v.translations.find((t=>t._key===e.id))},e.id):a(W,{languageField:o,source:C,documentId:l,schemaType:n,language:e,disabled:null!=(r=null==v?void 0:v.translations.filter((e=>{var t;return(null==(t=null==e?void 0:e.value)?void 0:t._ref)!==l})).some((t=>t._key===e.id)))&&r},e.id)})),b?null:r(i,{children:[D?null:a(O,{tone:"caution",padding:3,children:r(T,{size:1,children:["Choose a language to ",a("br",{}),"apply to ",a("strong",{children:"this Document"})]})}),D&&!F?a(O,{tone:"caution",padding:3,children:r(T,{size:1,children:["Change the current language value ",a("code",{children:D}),a("br",{}),"to one of the supported languages"]})}):null]})]}):null,a(V,{id:null==v?void 0:v._id})]})});return a(P,{constrainSize:!0,content:z,open:s,portal:!0,ref:g,children:a(y,{text:"Translations",mode:"bleed",disabled:!C,tone:!C||!b&&D&&F?void 0:"caution",icon:S,onClick:u,ref:m,selected:s})})}function H(e){const{id:t,addId:n,removeId:r}=e,i=c(t,""),l=d(t,""),o=u(),s=z.useMemo((()=>l.validation.length>0&&l.validation.find((e=>"error"===e.level))),[l]);return z.useEffect((()=>{s?n(t):r(t)}),[n,t,r,s]),i.draft?a(O,{border:!0,padding:2,tone:s?"critical":"positive",children:i.published?a(p,{layout:"default",value:i.published,schemaType:o.get(i.published._type)}):a(b,{})}):null}function J(e){const{translations:t}=e.value,n=s({apiVersion:"v2022-11-21"}),{projectId:i,dataset:l}=m(),o=f(),[c,d]=z.useState([]),u=E((e=>{d((t=>[...t,e]))}),[]),p=E((e=>{d((t=>t.filter((t=>t!==e))))}),[]),h=E((()=>{const e=t.map((e=>({documentId:e.value._ref})));n.request({uri:"/publish/".concat(i,"/").concat(l),method:"POST",body:e}).then((e=>{o.push({status:"success",title:"Success",description:"Bulk publish complete"})})).catch((e=>{console.error(e),o.push({status:"error",title:"Error",description:"Bulk publish failed"})}))}),[t,n,i,l,o]);return(null==t?void 0:t.length)>0?r(j,{space:4,children:[r(j,{space:3,children:[a(T,{weight:"bold",size:1,children:"Bulk publishing"}),r(T,{children:["There"," ",1===t.length?"is 1 document":"are ".concat(t.length," documents"),"."]}),c.length>0?r(T,{weight:"medium",children:[1===c.length?"1 draft has":"".concat(c.length," drafts have")," ","validation issues that must addressed first."]}):a(T,{children:"They are all valid."})]}),a(j,{space:2,children:t.map((e=>a(H,{id:e.value._ref,addId:u,removeId:p},e._key)))}),a(y,{text:"Simultaneously Publish ".concat(1===t.length?"1 Document":"".concat(t.length," Documents")),onClick:h,disabled:Boolean(c.length)})]}):null}const K={supportedLanguages:[],schemaTypes:[],languageField:"language",bulkPublish:!1},Q=h((e=>{const{supportedLanguages:n,schemaTypes:i,languageField:l,bulkPublish:s}=t(t({},K),e);return{name:"@sanity/document-internationalization",form:{components:{input:e=>s&&"root"===e.id&&"translation.metadata"===e.schemaType.name?r(j,{space:5,children:[a(J,t({},e)),e.renderDefault(e)]}):e.renderDefault(e)}},document:{unstable_languageFilter:(e,t)=>{const{schemaType:r,documentId:o}=t;return i.includes(r)?[...e,()=>((e,t)=>a(G,{supportedLanguages:n,schemaType:e,documentId:null!=t?t:"",languageField:l}))(r,o)]:e},badges:(e,t)=>{let{schemaType:a}=t;return i.includes(a)?[e=>function(e,t,n){const a=(null==e?void 0:e.draft)||(null==e?void 0:e.published),r=null==a?void 0:a[n],i=t.find((e=>e.id===r));return i?{label:i.id,title:i.title,color:"primary"}:null}(e,n,l),...e]:e}},schema:{types:[A(i)],templates:(e,t)=>{let{schema:a}=t;return[...e,...i.map((e=>{var t,n;return{id:"".concat(e,"-parameterized"),title:"".concat(null!=(n=null==(t=null==a?void 0:a.get(e))?void 0:t.title)?n:e,": with Language"),schemaType:e,parameters:[{name:"languageId",title:"Language ID",type:"string"}],value:e=>{let{languageId:t}=e;return{[l]:t}}}})),...i.flatMap((e=>n.map((t=>({id:"".concat(e,"-").concat(t.id),title:"".concat(t.title," Lesson"),schemaType:e,value:{[l]:t.id}})))))]}},plugins:[g({languages:n,fieldTypes:[o({name:"reference",type:"reference",to:i.map((e=>({type:e}))),options:{collapsed:!1,filter:e=>{let{parent:t,document:n}=e;var a;if(!t)return null;const r=!(null==(a=(Array.isArray(t)?t:[t]).find((e=>e._key)))?void 0:a._key);return r?n.schemaTypes?{filter:"_type in $schemaTypes && ".concat(l," == $language"),params:{schemaTypes:n.schemaTypes,language:r}}:{filter:"".concat(l," == $language"),params:{language:r}}:null}}},{strict:!1})]})]}}));export{Q as documentInternationalization};
1
+ function e(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function t(t){for(var a=1;a<arguments.length;a++){var r=null!=arguments[a]?arguments[a]:{};a%2?e(Object(r),!0).forEach((function(e){n(t,e,r[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(r)):e(Object(r)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(r,e))}))}return t}function n(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}import{jsx as a,jsxs as r,Fragment as i}from"react/jsx-runtime";import{defineType as l,defineField as o,useClient as s,useEditState as c,useValidationStatus as d,useSchema as u,SanityPreview as p,useWorkspace as m,definePlugin as h}from"sanity";import{internationalizedArray as g}from"sanity-plugin-internationalized-array";import{useToast as f,Button as y,Flex as v,Spinner as b,Text as _,Box as T,Badge as k,useClickOutside as I,Card as O,Stack as j,Popover as P}from"@sanity/ui";import{TranslateIcon as S,SplitVerticalIcon as w,CheckmarkIcon as x,AddIcon as C,CogIcon as D,ChevronRightIcon as F}from"@sanity/icons";import z,{useCallback as E,useState as L}from"react";import{uuid as B}from"@sanity/uuid";import{usePaneRouter as M}from"sanity/desk";import{RouterContext as $}from"sanity/router";import{useListeningQuery as U}from"sanity-plugin-utils";var A=e=>l({type:"document",name:"translation.metadata",title:"Translation metadata",icon:S,liveEdit:!0,fields:[o({name:"translations",type:"internationalizedArrayReference"}),o({name:"schemaTypes",description:"Used to filter the reference fields above so all translations share the same types.",type:"array",of:[{type:"string"}],options:{list:e},readOnly:e=>{let{value:t}=e;return Boolean(t)}})],preview:{select:{translations:"translations",documentSchemaTypes:"schemaTypes"},prepare(e){const{translations:t,documentSchemaTypes:n}=e,a=1===t.length?"1 Translation":"".concat(t.length," Translations"),r=t.length?t.map((e=>e._key.toUpperCase())).join(", "):"";return{title:a,subtitle:[r?"(".concat(r,")"):null,(null==n?void 0:n.length)?n.map((e=>e.toUpperCase())).join(", "):"No Schemas Defined"].filter(Boolean).join(" ")}}}});function N(e,t){const n=z.useContext($),{routerPanesState:a,groupIndex:r}=M();return z.useCallback((()=>{if(!n||!e||!t)return;const i=[...a];i.splice(r+1,0,[{id:e,params:{type:t}}]);const l=n.resolvePathFromState({panes:i});n.navigateUrl({path:l})}),[e,t,n,a,r])}function q(e,t,n){return{_key:e,value:{_type:"reference",_ref:t,_weak:!0,_strengthenOnPublish:{type:n}}}}function R(e){var n;const{index:i,language:l,languageField:o,schemaType:c,documentId:d,disabled:u,current:p,sourceId:m,sourceLanguageId:h,metadata:g,translation:I}=e,O=s(),j=f(),P=N(null==(n=null==I?void 0:I.value)?void 0:n._ref,c),S=E((()=>P()),[P]),D=E((async()=>{var e;const n=Boolean(null==g?void 0:g._id),a=O.transaction(),r=d.startsWith("drafts.")?[d,d.replace("drafts.","")]:[d,"drafts.".concat(d)],s=t(t({},await O.fetch("*[_id in $ids]|order(_updatedAt desc)[0]",{ids:r})),{},{_id:"drafts.".concat(B()),[o]:l.id});a.create(s);const u=null!=(e=null==g?void 0:g._id)?e:B(),p=q(l.id,s._id.replace("drafts.",""),c);if(n){const e="translations[".concat(i-1,"]"),t=O.patch(u).setIfMissing({translations:[]}).insert("before",e,[p]);a.patch(t)}else{const e=h?q(h,m,c):null;a.createIfNotExists({_id:u,_type:"translation.metadata",schemaTypes:[c],translations:[p,e].filter(Boolean)})}a.commit().then((()=>j.push({status:"success",title:"Created ".concat(l.title," translation"),description:n?"Updated Translations Metadata":"Created Translations Metadata"}))).catch((e=>(console.error(e),j.push({status:"error",title:"Error creating translation",description:e.message}))))}),[O,d,i,l,o,null==g?void 0:g._id,c,m,h,j]);return a(y,{onClick:I?S:D,mode:p?"default":"bleed",disabled:u||p,children:r(v,{gap:3,align:"center",children:[u?a(b,{}):a(_,{size:2,children:a(I?w:p?x:C,{})}),a(T,{flex:1,children:a(_,{children:l.title})}),a(k,{tone:u||p?"default":"primary",children:l.id})]})})}function V(e){const{id:t}=e,n=N(t,"translation.metadata");return a(y,{disabled:!t,mode:"ghost",text:"Manage Translations",icon:D,onClick:()=>n()})}function W(e){const{language:t,languageField:n,documentId:r,schemaType:i,source:l,disabled:o=!1}=e,c=s(),d=f(),u=z.useCallback((()=>{const e=l?l._id:"draft.".concat(r),a=c.transaction();l||a.createIfNotExists({_id:e,_type:i});const o=c.patch(e).set({[n]:t.id});a.patch(o),a.commit().then((()=>{d.push({title:"Set document language to ".concat(t.title),status:"success"})})).catch((e=>(console.error(e),d.push({title:"Failed to set document language to ".concat(t.title),status:"error"}))))}),[l,r,c,n,t,i,d]);return a(y,{mode:"ghost",text:t.title,icon:F,onClick:()=>u(),disabled:o,justify:"flex-start"})}function G(e){const{supportedLanguages:t,schemaType:n,documentId:l,languageField:o}=e,[s,d]=L(!1),u=E((()=>d((e=>!e))),[]),[p,m]=L(null),[h,g]=L(null),f=E((()=>d(!1)),[]);I(f,[p,h]);const{data:v,loading:b,error:k}=function(e,t){const{data:n,loading:a,error:r}=U("*[_type == $translationSchema && $id in translations[].value._ref][0]",{params:{id:e,translationSchema:"translation.metadata"}});return{data:n,loading:a,error:r}}(l),{draft:w,published:x}=c(l,n),C=w||x,D=null==C?void 0:C[o],F=t.some((e=>e.id===D)),z=a(T,{overflow:"auto",children:k?a(O,{tone:"critical",padding:2,children:r(_,{children:["Error: ",k]})}):r(j,{padding:1,space:1,children:[t.length>0?r(i,{children:[t.map(((e,t)=>{var r;return!b&&D&&F?a(R,{index:t,language:e,languageField:o,schemaType:n,documentId:l,disabled:b,current:e.id===D,metadata:v,sourceId:l,sourceLanguageId:D,translation:null==v?void 0:v.translations.find((t=>t._key===e.id))},e.id):a(W,{languageField:o,source:C,documentId:l,schemaType:n,language:e,disabled:null!=(r=null==v?void 0:v.translations.filter((e=>{var t;return(null==(t=null==e?void 0:e.value)?void 0:t._ref)!==l})).some((t=>t._key===e.id)))&&r},e.id)})),b?null:r(i,{children:[D?null:a(O,{tone:"caution",padding:3,children:r(_,{size:1,children:["Choose a language to ",a("br",{}),"apply to ",a("strong",{children:"this Document"})]})}),D&&!F?a(O,{tone:"caution",padding:3,children:r(_,{size:1,children:["Change the current language value ",a("code",{children:D}),a("br",{}),"to one of the supported languages"]})}):null]})]}):null,a(V,{id:null==v?void 0:v._id})]})});return a(P,{constrainSize:!0,content:z,open:s,portal:!0,ref:g,children:a(y,{text:"Translations",mode:"bleed",disabled:!C,tone:!C||!b&&D&&F?void 0:"caution",icon:S,onClick:u,ref:m,selected:s})})}function H(e){const{id:t,addId:n,removeId:r}=e,i=c(t,""),l=d(t,""),o=u(),s=z.useMemo((()=>l.validation.length>0&&l.validation.find((e=>"error"===e.level))),[l]);return z.useEffect((()=>{s?n(t):r(t)}),[n,t,r,s]),i.draft?a(O,{border:!0,padding:2,tone:s?"critical":"positive",children:i.published?a(p,{layout:"default",value:i.published,schemaType:o.get(i.published._type)}):a(b,{})}):null}function J(e){const{translations:t}=e.value,n=s({apiVersion:"v2022-11-21"}),{projectId:i,dataset:l}=m(),o=f(),[c,d]=z.useState([]),u=E((e=>{d((t=>[...t,e]))}),[]),p=E((e=>{d((t=>t.filter((t=>t!==e))))}),[]),h=E((()=>{const e=t.map((e=>({documentId:e.value._ref})));n.request({uri:"/publish/".concat(i,"/").concat(l),method:"POST",body:e}).then((e=>{o.push({status:"success",title:"Success",description:"Bulk publish complete"})})).catch((e=>{console.error(e),o.push({status:"error",title:"Error",description:"Bulk publish failed"})}))}),[t,n,i,l,o]);return(null==t?void 0:t.length)>0?r(j,{space:4,children:[r(j,{space:3,children:[a(_,{weight:"bold",size:1,children:"Bulk publishing"}),r(_,{children:["There"," ",1===t.length?"is 1 document":"are ".concat(t.length," documents"),"."]}),c.length>0?r(_,{weight:"medium",children:[1===c.length?"1 draft has":"".concat(c.length," drafts have")," ","validation issues that must addressed first."]}):a(_,{children:"They are all valid."})]}),a(j,{space:2,children:t.map((e=>a(H,{id:e.value._ref,addId:u,removeId:p},e._key)))}),a(y,{text:"Simultaneously Publish ".concat(1===t.length?"1 Document":"".concat(t.length," Documents")),onClick:h,disabled:Boolean(c.length)})]}):null}const K={supportedLanguages:[],schemaTypes:[],languageField:"language",bulkPublish:!1},Q=h((e=>{const{supportedLanguages:n,schemaTypes:i,languageField:l,bulkPublish:s}=t(t({},K),e);return{name:"@sanity/document-internationalization",form:{components:{input:e=>s&&"root"===e.id&&"translation.metadata"===e.schemaType.name?r(j,{space:5,children:[a(J,t({},e)),e.renderDefault(e)]}):e.renderDefault(e)}},document:{unstable_languageFilter:(e,t)=>{const{schemaType:r,documentId:o}=t;return i.includes(r)?[...e,()=>((e,t)=>a(G,{supportedLanguages:n,schemaType:e,documentId:null!=t?t:"",languageField:l}))(r,o)]:e},badges:(e,t)=>{let{schemaType:a}=t;return i.includes(a)?[e=>function(e,t,n){const a=(null==e?void 0:e.draft)||(null==e?void 0:e.published),r=null==a?void 0:a[n],i=t.find((e=>e.id===r));return i?{label:i.id,title:i.title,color:"primary"}:null}(e,n,l),...e]:e}},schema:{types:[A(i)],templates:(e,t)=>{let{schema:a}=t;return[...e,...i.map((e=>{var t,n;return{id:"".concat(e,"-parameterized"),title:"".concat(null!=(n=null==(t=null==a?void 0:a.get(e))?void 0:t.title)?n:e,": with Language"),schemaType:e,parameters:[{name:"languageId",title:"Language ID",type:"string"}],value:e=>{let{languageId:t}=e;return{[l]:t}}}})),...i.flatMap((e=>n.map((t=>({id:"".concat(e,"-").concat(t.id),title:"".concat(t.title," Lesson"),schemaType:e,value:{[l]:t.id}})))))]}},plugins:[g({languages:n,fieldTypes:[o({name:"reference",type:"reference",to:i.map((e=>({type:e}))),options:{collapsed:!1,filter:e=>{let{parent:t,document:n}=e;if(!t)return null;const a=(Array.isArray(t)?t:[t]).find((e=>e._key));return(null==a?void 0:a._key)?n.schemaTypes?{filter:"_type in $schemaTypes && ".concat(l," == $language"),params:{schemaTypes:n.schemaTypes,language:a._key}}:{filter:"".concat(l," == $language"),params:{language:a._key}}:null}}},{strict:!1})]})]}}));export{Q as documentInternationalization};
2
2
  //# sourceMappingURL=index.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/schema/translation/metadata.ts","../src/constants.ts","../src/hooks/useOpenInNewPane.tsx","../src/components/LanguageOption.tsx","../src/components/LanguageManage.tsx","../src/components/LanguagePatch.tsx","../src/components/MenuButton.tsx","../src/hooks/useLanguageMetadata.tsx","../src/components/BulkPublish/DocumentCheck.tsx","../src/components/BulkPublish/index.tsx","../src/plugin.tsx","../src/badges/index.tsx"],"sourcesContent":["import {defineType, defineField} from 'sanity'\nimport {TranslateIcon} from '@sanity/icons'\n\nimport {METADATA_SCHEMA_NAME} from '../../constants'\n\n// TODO: TS having a hard time determining the return type here. Likely a V3 type problem.\n// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\nexport default (schemaTypes: string[]) =>\n defineType({\n type: 'document',\n name: METADATA_SCHEMA_NAME,\n title: 'Translation metadata',\n icon: TranslateIcon,\n liveEdit: true,\n fields: [\n defineField({\n name: 'translations',\n type: 'internationalizedArrayReference',\n }),\n defineField({\n name: 'schemaTypes',\n description:\n 'Used to filter the reference fields above so all translations share the same types.',\n type: 'array',\n of: [{type: 'string'}],\n options: {list: schemaTypes},\n readOnly: ({value}) => Boolean(value),\n }),\n ],\n preview: {\n select: {\n translations: 'translations',\n documentSchemaTypes: 'schemaTypes',\n },\n prepare(selection) {\n const {translations, documentSchemaTypes} = selection\n const title =\n translations.length === 1 ? `1 Translation` : `${translations.length} Translations`\n const languageKeys = translations.length\n ? translations.map((t: {_key: string}) => t._key.toUpperCase()).join(', ')\n : ``\n const subtitle = [\n languageKeys ? `(${languageKeys})` : null,\n documentSchemaTypes?.length\n ? documentSchemaTypes.map((s: string) => s.toUpperCase()).join(`, `)\n : `No Schemas Defined`,\n ]\n .filter(Boolean)\n .join(` `)\n\n return {\n title,\n subtitle,\n }\n },\n },\n })\n","export const METADATA_SCHEMA_NAME = `translation.metadata`\n","import React from 'react'\nimport {usePaneRouter} from 'sanity/desk'\nimport {RouterContext} from 'sanity/router'\n\nexport function useOpenInNewPane(id?: string, type?: string) {\n const routerContext = React.useContext(RouterContext)\n const {routerPanesState, groupIndex} = usePaneRouter()\n\n const openInNewPane = React.useCallback(() => {\n if (!routerContext || !id || !type) {\n return\n }\n\n const panes = [...routerPanesState]\n panes.splice(groupIndex + 1, 0, [\n {\n id: id,\n params: {type},\n },\n ])\n\n const href = routerContext.resolvePathFromState({panes})\n routerContext.navigateUrl({path: href})\n }, [id, type, routerContext, routerPanesState, groupIndex])\n\n return openInNewPane\n}\n","import React, {useCallback} from 'react'\nimport {useClient} from 'sanity'\nimport {Button, Badge, Box, Flex, Text, useToast, Spinner} from '@sanity/ui'\nimport {uuid} from '@sanity/uuid'\nimport {SplitVerticalIcon, AddIcon, CheckmarkIcon} from '@sanity/icons'\n\nimport {Language, Metadata, TranslationReference} from '../types'\nimport {METADATA_SCHEMA_NAME} from '../constants'\nimport {useOpenInNewPane} from '../hooks/useOpenInNewPane'\n\ntype LanguageOptionProps = {\n language: Language\n languageField: string\n index: number\n schemaType: string\n documentId: string\n disabled: boolean\n current: boolean\n sourceId: string\n sourceLanguageId?: string\n metadata?: Metadata | null\n translation?: TranslationReference\n}\n\nfunction createReference(key: string, ref: string, type: string) {\n return {\n _key: key,\n value: {\n _type: 'reference',\n _ref: ref,\n _weak: true,\n _strengthenOnPublish: {\n type,\n },\n },\n }\n}\n\nexport default function LanguageOption(props: LanguageOptionProps) {\n const {\n index,\n language,\n languageField,\n schemaType,\n documentId,\n disabled,\n current,\n sourceId,\n sourceLanguageId,\n metadata,\n translation,\n } = props\n const client = useClient()\n const toast = useToast()\n\n const open = useOpenInNewPane(translation?.value?._ref, schemaType)\n const handleOpen = useCallback(() => open(), [open])\n\n const handleCreate = useCallback(async () => {\n const metadataExists = Boolean(metadata?._id)\n const transaction = client.transaction()\n\n // 1. Duplicate current document\n // 2. Update language\n // 3. Add to translation metadata\n const documentIds = documentId.startsWith(`drafts.`)\n ? [documentId, documentId.replace(`drafts.`, ``)]\n : [documentId, `drafts.${documentId}`]\n const latestDocument = await client.fetch(`*[_id in $ids]|order(_updatedAt desc)[0]`, {\n ids: documentIds,\n })\n const newTranslationDocument = {\n ...latestDocument,\n _id: `drafts.${uuid()}`,\n [languageField]: language.id,\n }\n\n transaction.create(newTranslationDocument)\n\n const metadataId = metadata?._id ?? uuid()\n const newTranslationReference = createReference(\n language.id,\n newTranslationDocument._id.replace(`drafts.`, ``),\n schemaType\n )\n\n // Create translation metadata document if it doesn't already exist\n if (metadataExists) {\n const path = `translations[${index - 1}]`\n const metadataPatch = client\n .patch(metadataId)\n .setIfMissing({translations: []})\n .insert(`before`, path, [newTranslationReference])\n\n transaction.patch(metadataPatch)\n } else {\n // Source language relies on a field named `language` on the document\n const sourceReference = sourceLanguageId\n ? createReference(sourceLanguageId, sourceId, schemaType)\n : null\n\n transaction.createIfNotExists({\n _id: metadataId,\n _type: METADATA_SCHEMA_NAME,\n schemaTypes: [schemaType],\n translations: [newTranslationReference, sourceReference].filter(Boolean),\n })\n }\n\n transaction\n .commit()\n .then(() => {\n // openDocumentInSidePane(metadataId, `translation.metadata`)\n return toast.push({\n status: 'success',\n title: `Created ${language.title} translation`,\n description: metadataExists\n ? `Updated Translations Metadata`\n : `Created Translations Metadata`,\n })\n })\n .catch((err) => {\n console.error(err)\n\n return toast.push({\n status: 'error',\n title: `Error creating translation`,\n description: err.message,\n })\n })\n }, [\n client,\n documentId,\n index,\n language,\n languageField,\n metadata?._id,\n schemaType,\n sourceId,\n sourceLanguageId,\n toast,\n ])\n\n return (\n <Button\n onClick={translation ? handleOpen : handleCreate}\n mode={current ? `default` : `bleed`}\n disabled={disabled || current}\n >\n <Flex gap={3} align=\"center\">\n {disabled ? (\n <Spinner />\n ) : (\n <Text size={2}>\n {/* eslint-disable-next-line no-nested-ternary */}\n {translation ? <SplitVerticalIcon /> : current ? <CheckmarkIcon /> : <AddIcon />}\n </Text>\n )}\n <Box flex={1}>\n <Text>{language.title}</Text>\n </Box>\n <Badge tone={disabled || current ? `default` : `primary`}>{language.id}</Badge>\n </Flex>\n </Button>\n )\n}\n","import React from 'react'\nimport {CogIcon} from '@sanity/icons'\nimport {Button} from '@sanity/ui'\n\nimport {useOpenInNewPane} from '../hooks/useOpenInNewPane'\nimport {METADATA_SCHEMA_NAME} from '../constants'\n\ntype LanguageManageProps = {\n id?: string\n}\n\nexport default function LanguageManage(props: LanguageManageProps) {\n const {id} = props\n const open = useOpenInNewPane(id, METADATA_SCHEMA_NAME)\n\n return (\n <Button\n disabled={!id}\n mode=\"ghost\"\n text=\"Manage Translations\"\n icon={CogIcon}\n onClick={() => open()}\n />\n )\n}\n","import React from 'react'\nimport {ChevronRightIcon} from '@sanity/icons'\nimport {Button, useToast} from '@sanity/ui'\nimport {SanityDocument, useClient} from 'sanity'\n\nimport {Language} from '../types'\n\ntype LanguagePatchProps = {\n language: Language\n languageField: string\n documentId: string\n schemaType: string\n source: SanityDocument | null\n disabled: boolean\n}\n\nexport default function LanguagePatch(props: LanguagePatchProps) {\n const {language, languageField, documentId, schemaType, source, disabled = false} = props\n const client = useClient()\n const toast = useToast()\n\n const handleClick = React.useCallback(() => {\n const currentId = source ? source._id : `draft.${documentId}`\n const transaction = client.transaction()\n\n if (!source) {\n transaction.createIfNotExists({\n _id: currentId,\n _type: schemaType,\n })\n }\n\n const patch = client.patch(currentId).set({[languageField]: language.id})\n transaction.patch(patch)\n\n transaction\n .commit()\n .then(() => {\n toast.push({\n title: `Set document language to ${language.title}`,\n status: `success`,\n })\n })\n .catch((err) => {\n console.error(err)\n\n return toast.push({\n title: `Failed to set document language to ${language.title}`,\n status: `error`,\n })\n })\n }, [source, documentId, client, languageField, language, schemaType, toast])\n\n return (\n <Button\n mode=\"ghost\"\n text={language.title}\n icon={ChevronRightIcon}\n onClick={() => handleClick()}\n disabled={disabled}\n justify=\"flex-start\"\n />\n )\n}\n","import React, {useCallback, useState} from 'react'\nimport {Text, Card, useClickOutside, Stack, Popover, Button, Box} from '@sanity/ui'\nimport {TranslateIcon} from '@sanity/icons'\nimport {useEditState} from 'sanity'\n\nimport {Language} from '../types'\nimport LanguageOption from './LanguageOption'\nimport {useTranslationMetadata} from '../hooks/useLanguageMetadata'\nimport LanguageManage from './LanguageManage'\nimport LanguagePatch from './LanguagePatch'\n\ntype MenuButtonProps = {\n supportedLanguages: Language[]\n schemaType: string\n documentId: string\n languageField: string\n}\n\nexport default function MenuButton(props: MenuButtonProps) {\n const {supportedLanguages, schemaType, documentId, languageField} = props\n\n const [open, setOpen] = useState(false)\n const handleClick = useCallback(() => setOpen((o) => !o), [])\n const [button, setButton] = useState<HTMLElement | null>(null)\n const [popover, setPopover] = useState<HTMLElement | null>(null)\n const handleClickOutside = useCallback(() => setOpen(false), [])\n useClickOutside(handleClickOutside, [button, popover])\n const {data: metadata, loading, error} = useTranslationMetadata(documentId, schemaType)\n const {draft, published} = useEditState(documentId, schemaType)\n const source = draft || published\n\n const sourceLanguageId = source?.[languageField] as string | undefined\n const sourceLanguageIsValid = supportedLanguages.some((l) => l.id === sourceLanguageId)\n\n const content = (\n <Box overflow=\"auto\">\n {error ? (\n <Card tone=\"critical\" padding={2}>\n <Text>Error: {error}</Text>\n </Card>\n ) : (\n <Stack padding={1} space={1}>\n {supportedLanguages.length > 0 ? (\n <>\n {supportedLanguages.map((language, langIndex) =>\n !loading && sourceLanguageId && sourceLanguageIsValid ? (\n // Button to duplicate this document to a new translation\n // And either create or update the metadata document\n <LanguageOption\n key={language.id}\n index={langIndex}\n language={language}\n languageField={languageField}\n schemaType={schemaType}\n documentId={documentId}\n disabled={loading}\n current={language.id === sourceLanguageId}\n metadata={metadata}\n sourceId={documentId}\n sourceLanguageId={sourceLanguageId}\n translation={metadata?.translations.find((t) => t._key === language.id)}\n />\n ) : (\n // Button to set a language field on *this* document\n <LanguagePatch\n key={language.id}\n languageField={languageField}\n source={source}\n documentId={documentId}\n schemaType={schemaType}\n language={language}\n // Only allow language patch change to:\n // - Keys not in metadata\n // - The key of this document in the metadata\n disabled={\n metadata?.translations\n .filter((t) => t?.value?._ref !== documentId)\n .some((t) => t._key === language.id) ?? false\n }\n />\n )\n )}\n {/* Once metadata is loaded, there may be issues */}\n {loading ? null : (\n <>\n {/* Current document has no language field */}\n {sourceLanguageId ? null : (\n <Card tone=\"caution\" padding={3}>\n <Text size={1}>\n Choose a language to <br />\n apply to <strong>this Document</strong>\n </Text>\n </Card>\n )}\n {/* Current document has an invalid language field */}\n {sourceLanguageId && !sourceLanguageIsValid ? (\n <Card tone=\"caution\" padding={3}>\n <Text size={1}>\n Change the current language value <code>{sourceLanguageId}</code>\n <br />\n to one of the supported languages\n </Text>\n </Card>\n ) : null}\n </>\n )}\n </>\n ) : null}\n <LanguageManage id={metadata?._id} />\n </Stack>\n )}\n </Box>\n )\n\n return (\n <Popover constrainSize content={content} open={open} portal ref={setPopover}>\n <Button\n text=\"Translations\"\n mode=\"bleed\"\n disabled={!source}\n tone={\n !source || (!loading && sourceLanguageId && sourceLanguageIsValid) ? undefined : `caution`\n }\n icon={TranslateIcon}\n onClick={handleClick}\n ref={setButton}\n selected={open}\n />\n </Popover>\n )\n}\n","import React from 'react'\nimport {useListeningQuery} from 'sanity-plugin-utils'\nimport {METADATA_SCHEMA_NAME} from '../constants'\n\nimport {Metadata} from '../types'\n\nexport function useTranslationMetadata(\n id: string,\n schemaType: string\n): {\n data: Metadata | null\n loading: boolean\n error: boolean\n} {\n const query = `*[_type == $translationSchema && $id in translations[].value._ref][0]`\n const {data, loading, error} = useListeningQuery<Metadata>(query, {\n params: {id, translationSchema: METADATA_SCHEMA_NAME},\n })\n\n return {data, loading, error}\n}\n","import React from 'react'\nimport {Card, Spinner} from '@sanity/ui'\nimport {\n useEditState,\n useValidationStatus,\n SanityPreview as Preview,\n SchemaType,\n useSchema,\n} from 'sanity'\n\ntype DocumentCheckProps = {\n id: string\n addId: (id: string) => void\n removeId: (id: string) => void\n}\n\n// Check if the document has a draft\n// Check if that draft is valid\n// Report back to parent that it can be added to bulk publish\nexport default function DocumentCheck(props: DocumentCheckProps) {\n const {id, addId, removeId} = props\n const editState = useEditState(id, ``)\n const validationStatus = useValidationStatus(id, ``)\n const schema = useSchema()\n\n const validationHasErrors = React.useMemo(() => {\n return (\n validationStatus.validation.length > 0 &&\n validationStatus.validation.find((item) => item.level === 'error')\n )\n }, [validationStatus])\n\n React.useEffect(() => {\n if (validationHasErrors) {\n addId(id)\n } else {\n removeId(id)\n }\n }, [addId, id, removeId, validationHasErrors])\n\n // We only care about drafts\n if (!editState.draft) {\n return null\n }\n\n return (\n <Card border padding={2} tone={validationHasErrors ? `critical` : `positive`}>\n {editState.published ? (\n <Preview\n layout=\"default\"\n value={editState.published}\n schemaType={schema.get(editState.published._type) as SchemaType}\n />\n ) : (\n <Spinner />\n )}\n </Card>\n )\n}\n","import React, {useCallback} from 'react'\nimport {Box, Text, Stack, Button, useToast} from '@sanity/ui'\nimport {\n InputProps,\n Reference,\n SanityDocument,\n KeyedObject,\n TypedObject,\n useClient,\n useWorkspace,\n} from 'sanity'\nimport DocumentCheck from './DocumentCheck'\n\nexport type TranslationReference = KeyedObject & TypedObject & {value: Reference}\n\nexport type TranslationMetadataDocument = SanityDocument & {\n translations: TranslationReference[]\n schemaTypes: string[]\n}\n\nexport default function BulkPublish(props: InputProps) {\n const {translations} = props.value as TranslationMetadataDocument\n const client = useClient({apiVersion: `v2022-11-21`})\n const {projectId, dataset} = useWorkspace()\n const toast = useToast()\n const [invalidIds, setInvalidIds] = React.useState<string[]>([])\n\n const addId = useCallback((id: string) => {\n setInvalidIds((ids) => [...ids, id])\n }, [])\n\n const removeId = useCallback((id: string) => {\n setInvalidIds((ids) => ids.filter((i) => i !== id))\n }, [])\n\n const handleBulkPublish = useCallback(() => {\n const body = translations.map((translation) => ({documentId: translation.value._ref}))\n client\n .request({\n uri: `/publish/${projectId}/${dataset}`,\n method: 'POST',\n body,\n })\n .then((res) => {\n toast.push({\n status: 'success',\n title: 'Success',\n description: 'Bulk publish complete',\n })\n })\n .catch((err) => {\n console.error(err)\n toast.push({\n status: 'error',\n title: 'Error',\n description: 'Bulk publish failed',\n })\n })\n }, [translations, client, projectId, dataset, toast])\n\n // TODO: Hide all this if none of the documents have drafts\n return translations?.length > 0 ? (\n <Stack space={4}>\n <Stack space={3}>\n <Text weight=\"bold\" size={1}>\n Bulk publishing\n </Text>\n <Text>\n There{' '}\n {translations.length === 1 ? `is 1 document` : `are ${translations.length} documents`}.\n </Text>\n {invalidIds.length > 0 ? (\n <Text weight=\"medium\">\n {invalidIds.length === 1 ? `1 draft has` : `${invalidIds.length} drafts have`}{' '}\n validation issues that must addressed first.\n </Text>\n ) : (\n <Text>They are all valid.</Text>\n )}\n </Stack>\n <Stack space={2}>\n {translations.map((translation) => (\n <DocumentCheck\n key={translation._key}\n id={translation.value._ref}\n addId={addId}\n removeId={removeId}\n />\n ))}\n </Stack>\n <Button\n text={`Simultaneously Publish ${\n translations.length === 1 ? `1 Document` : `${translations.length} Documents`\n }`}\n onClick={handleBulkPublish}\n disabled={Boolean(invalidIds.length)}\n />\n </Stack>\n ) : null\n}\n","import React from 'react'\nimport {definePlugin, defineField} from 'sanity'\nimport {internationalizedArray} from 'sanity-plugin-internationalized-array'\nimport {Stack} from '@sanity/ui'\n\nimport metadata from './schema/translation/metadata'\nimport MenuButton from './components/MenuButton'\nimport {PluginConfig} from './types'\nimport {LanguageBadge} from './badges'\nimport {METADATA_SCHEMA_NAME} from './constants'\nimport BulkPublish from './components/BulkPublish'\n\nconst DEFAULT_CONFIG = {\n supportedLanguages: [],\n schemaTypes: [],\n languageField: `language`,\n bulkPublish: false,\n}\n\nexport const documentInternationalization = definePlugin<PluginConfig>((config) => {\n const {supportedLanguages, schemaTypes, languageField, bulkPublish} = {\n ...DEFAULT_CONFIG,\n ...config,\n }\n\n const renderLanguageFilter = (schemaType: string, documentId?: string) => {\n return (\n <MenuButton\n supportedLanguages={supportedLanguages}\n schemaType={schemaType}\n documentId={documentId ?? ``}\n languageField={languageField}\n />\n )\n }\n\n return {\n name: '@sanity/document-internationalization',\n\n // Adds:\n // - A bulk-publishing UI component to the form\n // - Will only work for projects on a compatible plan\n form: {\n components: {\n input: (props) => {\n if (\n bulkPublish &&\n props.id === 'root' &&\n props.schemaType.name === METADATA_SCHEMA_NAME\n ) {\n return (\n <Stack space={5}>\n <BulkPublish {...props} />\n {props.renderDefault(props)}\n </Stack>\n )\n }\n\n return props.renderDefault(props)\n },\n },\n },\n\n // Adds:\n // - The `Translations` dropdown to the editing form\n // - `Badges` to documents with a language value\n document: {\n unstable_languageFilter: (prev, ctx) => {\n const {schemaType, documentId} = ctx\n\n return schemaTypes.includes(schemaType)\n ? [...prev, () => renderLanguageFilter(schemaType, documentId)]\n : prev\n },\n badges: (prev, {schemaType}) => {\n if (!schemaTypes.includes(schemaType)) {\n return prev\n }\n\n return [(props) => LanguageBadge(props, supportedLanguages, languageField), ...prev]\n },\n },\n\n // Adds:\n // - The `Translations metadata` document type to the schema\n schema: {\n // Create the metadata document type\n types: [metadata(schemaTypes)],\n\n // For every schema type this plugin is enabled on\n // Create an initial value template to set the language\n templates: (prev, {schema}) => {\n const parameterizedTemplates = schemaTypes.map((schemaType) => ({\n id: `${schemaType}-parameterized`,\n title: `${schema?.get(schemaType)?.title ?? schemaType}: with Language`,\n schemaType,\n parameters: [{name: `languageId`, title: `Language ID`, type: `string`}],\n value: ({languageId}: {languageId: string}) => ({\n [languageField]: languageId,\n }),\n }))\n\n const staticTemplates = schemaTypes.flatMap((schemaType) => {\n return supportedLanguages.map((language) => ({\n id: `${schemaType}-${language.id}`,\n title: `${language.title} Lesson`,\n schemaType,\n value: {\n [languageField]: language.id,\n },\n }))\n })\n\n return [...prev, ...parameterizedTemplates, ...staticTemplates]\n },\n },\n\n // Uses:\n // - `sanity-plugin-internationalized-array` to maintain the translations array\n plugins: [\n // Translation metadata stores its references using this plugin\n // It cuts down on attribute usage and gives UI conveniences to add new translations\n internationalizedArray({\n languages: supportedLanguages,\n fieldTypes: [\n // TODO: The plugin should allow this kind of input\n // @ts-ignore\n defineField(\n {\n name: 'reference',\n type: 'reference',\n to: schemaTypes.map((type) => ({type: type})),\n // TODO: Add a validation rule to *ensure* the document's language matches the array key\n // Reference filters don't actually enforce validation!\n // validation: (Rule) => Rule.custom(),\n options: {\n collapsed: false,\n // TODO: Update type once it knows the values of this filter\n // @ts-ignore\n filter: ({parent, document}) => {\n if (!parent) return null\n\n // I'm not sure in what instance there's an array of parents\n // But the Type suggests it's possible\n const parentArray = Array.isArray(parent) ? parent : [parent]\n const language = !parentArray.find((p) => p._key)?._key\n\n if (!language) return null\n\n if (document.schemaTypes) {\n return {\n filter: `_type in $schemaTypes && ${languageField} == $language`,\n params: {schemaTypes: document.schemaTypes, language},\n }\n }\n\n return {\n filter: `${languageField} == $language`,\n params: {language},\n }\n },\n },\n },\n {strict: false}\n ),\n ],\n }),\n ],\n }\n})\n","import {DocumentBadgeDescription, DocumentBadgeProps} from 'sanity'\n\nimport {Language} from '../types'\n\nexport function LanguageBadge(\n props: DocumentBadgeProps,\n supportedLanguages: Language[],\n languageField: string\n): DocumentBadgeDescription | null {\n const source = props?.draft || props?.published\n const languageId = source?.[languageField]\n const language = supportedLanguages.find((l) => l.id === languageId)\n\n if (!language) {\n return null\n }\n\n return {\n label: language.id,\n title: language.title,\n color: `primary`,\n }\n}\n"],"names":["metadata","schemaTypes","defineType","type","name","title","icon","TranslateIcon","liveEdit","fields","defineField","description","of","options","list","readOnly","_ref","value","Boolean","preview","select","translations","documentSchemaTypes","prepare","selection","length","languageKeys","map","t","_key","toUpperCase","join","subtitle","s","filter","useOpenInNewPane","id","routerContext","React","useContext","RouterContext","routerPanesState","groupIndex","usePaneRouter","useCallback","panes","splice","params","href","resolvePathFromState","navigateUrl","path","createReference","key","ref","_type","_weak","_strengthenOnPublish","LanguageOption","props","_a","index","language","languageField","schemaType","documentId","disabled","current","sourceId","sourceLanguageId","translation","client","useClient","toast","useToast","open","handleOpen","handleCreate","async","metadataExists","_id","transaction","documentIds","startsWith","replace","concat","newTranslationDocument","fetch","ids","uuid","create","metadataId","newTranslationReference","metadataPatch","patch","setIfMissing","insert","sourceReference","createIfNotExists","commit","then","push","status","catch","err","console","error","message","jsx","Button","onClick","mode","children","jsxs","Flex","gap","align","Spinner","Text","size","SplitVerticalIcon","CheckmarkIcon","AddIcon","Box","flex","Badge","tone","LanguageManage","text","CogIcon","LanguagePatch","source","handleClick","currentId","set","ChevronRightIcon","justify","MenuButton","supportedLanguages","setOpen","useState","o","button","setButton","popover","setPopover","handleClickOutside","useClickOutside","data","loading","useListeningQuery","translationSchema","useTranslationMetadata","draft","published","useEditState","sourceLanguageIsValid","some","l","content","overflow","Card","padding","Stack","space","Fragment","langIndex","find","Popover","constrainSize","portal","selected","DocumentCheck","addId","removeId","editState","validationStatus","useValidationStatus","schema","useSchema","validationHasErrors","useMemo","validation","item","level","useEffect","border","Preview","layout","get","BulkPublish","apiVersion","projectId","dataset","useWorkspace","invalidIds","setInvalidIds","i","handleBulkPublish","body","request","uri","method","res","weight","DEFAULT_CONFIG","bulkPublish","documentInternationalization","definePlugin","config","form","components","input","_objectSpread","renderDefault","document","unstable_languageFilter","prev","ctx","includes","renderLanguageFilter","badges","_ref2","languageId","label","color","LanguageBadge","types","templates","_ref3","_b","parameters","_ref4","flatMap","plugins","internationalizedArray","languages","fieldTypes","to","collapsed","_ref5","parent","Array","isArray","p","strict"],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/schema/translation/metadata.ts","../src/constants.ts","../src/hooks/useOpenInNewPane.tsx","../src/components/LanguageOption.tsx","../src/components/LanguageManage.tsx","../src/components/LanguagePatch.tsx","../src/components/MenuButton.tsx","../src/hooks/useLanguageMetadata.tsx","../src/components/BulkPublish/DocumentCheck.tsx","../src/components/BulkPublish/index.tsx","../src/plugin.tsx","../src/badges/index.tsx"],"sourcesContent":["import {defineType, defineField} from 'sanity'\nimport {TranslateIcon} from '@sanity/icons'\n\nimport {METADATA_SCHEMA_NAME} from '../../constants'\n\n// TODO: TS having a hard time determining the return type here. Likely a V3 type problem.\n// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\nexport default (schemaTypes: string[]) =>\n defineType({\n type: 'document',\n name: METADATA_SCHEMA_NAME,\n title: 'Translation metadata',\n icon: TranslateIcon,\n liveEdit: true,\n fields: [\n defineField({\n name: 'translations',\n type: 'internationalizedArrayReference',\n }),\n defineField({\n name: 'schemaTypes',\n description:\n 'Used to filter the reference fields above so all translations share the same types.',\n type: 'array',\n of: [{type: 'string'}],\n options: {list: schemaTypes},\n readOnly: ({value}) => Boolean(value),\n }),\n ],\n preview: {\n select: {\n translations: 'translations',\n documentSchemaTypes: 'schemaTypes',\n },\n prepare(selection) {\n const {translations, documentSchemaTypes} = selection\n const title =\n translations.length === 1 ? `1 Translation` : `${translations.length} Translations`\n const languageKeys = translations.length\n ? translations.map((t: {_key: string}) => t._key.toUpperCase()).join(', ')\n : ``\n const subtitle = [\n languageKeys ? `(${languageKeys})` : null,\n documentSchemaTypes?.length\n ? documentSchemaTypes.map((s: string) => s.toUpperCase()).join(`, `)\n : `No Schemas Defined`,\n ]\n .filter(Boolean)\n .join(` `)\n\n return {\n title,\n subtitle,\n }\n },\n },\n })\n","export const METADATA_SCHEMA_NAME = `translation.metadata`\n","import React from 'react'\nimport {usePaneRouter} from 'sanity/desk'\nimport {RouterContext} from 'sanity/router'\n\nexport function useOpenInNewPane(id?: string, type?: string) {\n const routerContext = React.useContext(RouterContext)\n const {routerPanesState, groupIndex} = usePaneRouter()\n\n const openInNewPane = React.useCallback(() => {\n if (!routerContext || !id || !type) {\n return\n }\n\n const panes = [...routerPanesState]\n panes.splice(groupIndex + 1, 0, [\n {\n id: id,\n params: {type},\n },\n ])\n\n const href = routerContext.resolvePathFromState({panes})\n routerContext.navigateUrl({path: href})\n }, [id, type, routerContext, routerPanesState, groupIndex])\n\n return openInNewPane\n}\n","import React, {useCallback} from 'react'\nimport {useClient} from 'sanity'\nimport {Button, Badge, Box, Flex, Text, useToast, Spinner} from '@sanity/ui'\nimport {uuid} from '@sanity/uuid'\nimport {SplitVerticalIcon, AddIcon, CheckmarkIcon} from '@sanity/icons'\n\nimport {Language, Metadata, TranslationReference} from '../types'\nimport {METADATA_SCHEMA_NAME} from '../constants'\nimport {useOpenInNewPane} from '../hooks/useOpenInNewPane'\n\ntype LanguageOptionProps = {\n language: Language\n languageField: string\n index: number\n schemaType: string\n documentId: string\n disabled: boolean\n current: boolean\n sourceId: string\n sourceLanguageId?: string\n metadata?: Metadata | null\n translation?: TranslationReference\n}\n\nfunction createReference(key: string, ref: string, type: string) {\n return {\n _key: key,\n value: {\n _type: 'reference',\n _ref: ref,\n _weak: true,\n _strengthenOnPublish: {\n type,\n },\n },\n }\n}\n\nexport default function LanguageOption(props: LanguageOptionProps) {\n const {\n index,\n language,\n languageField,\n schemaType,\n documentId,\n disabled,\n current,\n sourceId,\n sourceLanguageId,\n metadata,\n translation,\n } = props\n const client = useClient()\n const toast = useToast()\n\n const open = useOpenInNewPane(translation?.value?._ref, schemaType)\n const handleOpen = useCallback(() => open(), [open])\n\n const handleCreate = useCallback(async () => {\n const metadataExists = Boolean(metadata?._id)\n const transaction = client.transaction()\n\n // 1. Duplicate current document\n // 2. Update language\n // 3. Add to translation metadata\n const documentIds = documentId.startsWith(`drafts.`)\n ? [documentId, documentId.replace(`drafts.`, ``)]\n : [documentId, `drafts.${documentId}`]\n const latestDocument = await client.fetch(`*[_id in $ids]|order(_updatedAt desc)[0]`, {\n ids: documentIds,\n })\n const newTranslationDocument = {\n ...latestDocument,\n _id: `drafts.${uuid()}`,\n [languageField]: language.id,\n }\n\n transaction.create(newTranslationDocument)\n\n const metadataId = metadata?._id ?? uuid()\n const newTranslationReference = createReference(\n language.id,\n newTranslationDocument._id.replace(`drafts.`, ``),\n schemaType\n )\n\n // Create translation metadata document if it doesn't already exist\n if (metadataExists) {\n const path = `translations[${index - 1}]`\n const metadataPatch = client\n .patch(metadataId)\n .setIfMissing({translations: []})\n .insert(`before`, path, [newTranslationReference])\n\n transaction.patch(metadataPatch)\n } else {\n // Source language relies on a field named `language` on the document\n const sourceReference = sourceLanguageId\n ? createReference(sourceLanguageId, sourceId, schemaType)\n : null\n\n transaction.createIfNotExists({\n _id: metadataId,\n _type: METADATA_SCHEMA_NAME,\n schemaTypes: [schemaType],\n translations: [newTranslationReference, sourceReference].filter(Boolean),\n })\n }\n\n transaction\n .commit()\n .then(() => {\n // openDocumentInSidePane(metadataId, `translation.metadata`)\n return toast.push({\n status: 'success',\n title: `Created ${language.title} translation`,\n description: metadataExists\n ? `Updated Translations Metadata`\n : `Created Translations Metadata`,\n })\n })\n .catch((err) => {\n console.error(err)\n\n return toast.push({\n status: 'error',\n title: `Error creating translation`,\n description: err.message,\n })\n })\n }, [\n client,\n documentId,\n index,\n language,\n languageField,\n metadata?._id,\n schemaType,\n sourceId,\n sourceLanguageId,\n toast,\n ])\n\n return (\n <Button\n onClick={translation ? handleOpen : handleCreate}\n mode={current ? `default` : `bleed`}\n disabled={disabled || current}\n >\n <Flex gap={3} align=\"center\">\n {disabled ? (\n <Spinner />\n ) : (\n <Text size={2}>\n {/* eslint-disable-next-line no-nested-ternary */}\n {translation ? <SplitVerticalIcon /> : current ? <CheckmarkIcon /> : <AddIcon />}\n </Text>\n )}\n <Box flex={1}>\n <Text>{language.title}</Text>\n </Box>\n <Badge tone={disabled || current ? `default` : `primary`}>{language.id}</Badge>\n </Flex>\n </Button>\n )\n}\n","import React from 'react'\nimport {CogIcon} from '@sanity/icons'\nimport {Button} from '@sanity/ui'\n\nimport {useOpenInNewPane} from '../hooks/useOpenInNewPane'\nimport {METADATA_SCHEMA_NAME} from '../constants'\n\ntype LanguageManageProps = {\n id?: string\n}\n\nexport default function LanguageManage(props: LanguageManageProps) {\n const {id} = props\n const open = useOpenInNewPane(id, METADATA_SCHEMA_NAME)\n\n return (\n <Button\n disabled={!id}\n mode=\"ghost\"\n text=\"Manage Translations\"\n icon={CogIcon}\n onClick={() => open()}\n />\n )\n}\n","import React from 'react'\nimport {ChevronRightIcon} from '@sanity/icons'\nimport {Button, useToast} from '@sanity/ui'\nimport {SanityDocument, useClient} from 'sanity'\n\nimport {Language} from '../types'\n\ntype LanguagePatchProps = {\n language: Language\n languageField: string\n documentId: string\n schemaType: string\n source: SanityDocument | null\n disabled: boolean\n}\n\nexport default function LanguagePatch(props: LanguagePatchProps) {\n const {language, languageField, documentId, schemaType, source, disabled = false} = props\n const client = useClient()\n const toast = useToast()\n\n const handleClick = React.useCallback(() => {\n const currentId = source ? source._id : `draft.${documentId}`\n const transaction = client.transaction()\n\n if (!source) {\n transaction.createIfNotExists({\n _id: currentId,\n _type: schemaType,\n })\n }\n\n const patch = client.patch(currentId).set({[languageField]: language.id})\n transaction.patch(patch)\n\n transaction\n .commit()\n .then(() => {\n toast.push({\n title: `Set document language to ${language.title}`,\n status: `success`,\n })\n })\n .catch((err) => {\n console.error(err)\n\n return toast.push({\n title: `Failed to set document language to ${language.title}`,\n status: `error`,\n })\n })\n }, [source, documentId, client, languageField, language, schemaType, toast])\n\n return (\n <Button\n mode=\"ghost\"\n text={language.title}\n icon={ChevronRightIcon}\n onClick={() => handleClick()}\n disabled={disabled}\n justify=\"flex-start\"\n />\n )\n}\n","import React, {useCallback, useState} from 'react'\nimport {Text, Card, useClickOutside, Stack, Popover, Button, Box} from '@sanity/ui'\nimport {TranslateIcon} from '@sanity/icons'\nimport {useEditState} from 'sanity'\n\nimport {Language} from '../types'\nimport LanguageOption from './LanguageOption'\nimport {useTranslationMetadata} from '../hooks/useLanguageMetadata'\nimport LanguageManage from './LanguageManage'\nimport LanguagePatch from './LanguagePatch'\n\ntype MenuButtonProps = {\n supportedLanguages: Language[]\n schemaType: string\n documentId: string\n languageField: string\n}\n\nexport default function MenuButton(props: MenuButtonProps) {\n const {supportedLanguages, schemaType, documentId, languageField} = props\n\n const [open, setOpen] = useState(false)\n const handleClick = useCallback(() => setOpen((o) => !o), [])\n const [button, setButton] = useState<HTMLElement | null>(null)\n const [popover, setPopover] = useState<HTMLElement | null>(null)\n const handleClickOutside = useCallback(() => setOpen(false), [])\n useClickOutside(handleClickOutside, [button, popover])\n const {data: metadata, loading, error} = useTranslationMetadata(documentId, schemaType)\n const {draft, published} = useEditState(documentId, schemaType)\n const source = draft || published\n\n const sourceLanguageId = source?.[languageField] as string | undefined\n const sourceLanguageIsValid = supportedLanguages.some((l) => l.id === sourceLanguageId)\n\n const content = (\n <Box overflow=\"auto\">\n {error ? (\n <Card tone=\"critical\" padding={2}>\n <Text>Error: {error}</Text>\n </Card>\n ) : (\n <Stack padding={1} space={1}>\n {supportedLanguages.length > 0 ? (\n <>\n {supportedLanguages.map((language, langIndex) =>\n !loading && sourceLanguageId && sourceLanguageIsValid ? (\n // Button to duplicate this document to a new translation\n // And either create or update the metadata document\n <LanguageOption\n key={language.id}\n index={langIndex}\n language={language}\n languageField={languageField}\n schemaType={schemaType}\n documentId={documentId}\n disabled={loading}\n current={language.id === sourceLanguageId}\n metadata={metadata}\n sourceId={documentId}\n sourceLanguageId={sourceLanguageId}\n translation={metadata?.translations.find((t) => t._key === language.id)}\n />\n ) : (\n // Button to set a language field on *this* document\n <LanguagePatch\n key={language.id}\n languageField={languageField}\n source={source}\n documentId={documentId}\n schemaType={schemaType}\n language={language}\n // Only allow language patch change to:\n // - Keys not in metadata\n // - The key of this document in the metadata\n disabled={\n metadata?.translations\n .filter((t) => t?.value?._ref !== documentId)\n .some((t) => t._key === language.id) ?? false\n }\n />\n )\n )}\n {/* Once metadata is loaded, there may be issues */}\n {loading ? null : (\n <>\n {/* Current document has no language field */}\n {sourceLanguageId ? null : (\n <Card tone=\"caution\" padding={3}>\n <Text size={1}>\n Choose a language to <br />\n apply to <strong>this Document</strong>\n </Text>\n </Card>\n )}\n {/* Current document has an invalid language field */}\n {sourceLanguageId && !sourceLanguageIsValid ? (\n <Card tone=\"caution\" padding={3}>\n <Text size={1}>\n Change the current language value <code>{sourceLanguageId}</code>\n <br />\n to one of the supported languages\n </Text>\n </Card>\n ) : null}\n </>\n )}\n </>\n ) : null}\n <LanguageManage id={metadata?._id} />\n </Stack>\n )}\n </Box>\n )\n\n return (\n <Popover constrainSize content={content} open={open} portal ref={setPopover}>\n <Button\n text=\"Translations\"\n mode=\"bleed\"\n disabled={!source}\n tone={\n !source || (!loading && sourceLanguageId && sourceLanguageIsValid) ? undefined : `caution`\n }\n icon={TranslateIcon}\n onClick={handleClick}\n ref={setButton}\n selected={open}\n />\n </Popover>\n )\n}\n","import React from 'react'\nimport {useListeningQuery} from 'sanity-plugin-utils'\nimport {METADATA_SCHEMA_NAME} from '../constants'\n\nimport {Metadata} from '../types'\n\nexport function useTranslationMetadata(\n id: string,\n schemaType: string\n): {\n data: Metadata | null\n loading: boolean\n error: boolean\n} {\n const query = `*[_type == $translationSchema && $id in translations[].value._ref][0]`\n const {data, loading, error} = useListeningQuery<Metadata>(query, {\n params: {id, translationSchema: METADATA_SCHEMA_NAME},\n })\n\n return {data, loading, error}\n}\n","import React from 'react'\nimport {Card, Spinner} from '@sanity/ui'\nimport {\n useEditState,\n useValidationStatus,\n SanityPreview as Preview,\n SchemaType,\n useSchema,\n} from 'sanity'\n\ntype DocumentCheckProps = {\n id: string\n addId: (id: string) => void\n removeId: (id: string) => void\n}\n\n// Check if the document has a draft\n// Check if that draft is valid\n// Report back to parent that it can be added to bulk publish\nexport default function DocumentCheck(props: DocumentCheckProps) {\n const {id, addId, removeId} = props\n const editState = useEditState(id, ``)\n const validationStatus = useValidationStatus(id, ``)\n const schema = useSchema()\n\n const validationHasErrors = React.useMemo(() => {\n return (\n validationStatus.validation.length > 0 &&\n validationStatus.validation.find((item) => item.level === 'error')\n )\n }, [validationStatus])\n\n React.useEffect(() => {\n if (validationHasErrors) {\n addId(id)\n } else {\n removeId(id)\n }\n }, [addId, id, removeId, validationHasErrors])\n\n // We only care about drafts\n if (!editState.draft) {\n return null\n }\n\n return (\n <Card border padding={2} tone={validationHasErrors ? `critical` : `positive`}>\n {editState.published ? (\n <Preview\n layout=\"default\"\n value={editState.published}\n schemaType={schema.get(editState.published._type) as SchemaType}\n />\n ) : (\n <Spinner />\n )}\n </Card>\n )\n}\n","import React, {useCallback} from 'react'\nimport {Box, Text, Stack, Button, useToast} from '@sanity/ui'\nimport {\n InputProps,\n Reference,\n SanityDocument,\n KeyedObject,\n TypedObject,\n useClient,\n useWorkspace,\n} from 'sanity'\nimport DocumentCheck from './DocumentCheck'\n\nexport type TranslationReference = KeyedObject & TypedObject & {value: Reference}\n\nexport type TranslationMetadataDocument = SanityDocument & {\n translations: TranslationReference[]\n schemaTypes: string[]\n}\n\nexport default function BulkPublish(props: InputProps) {\n const {translations} = props.value as TranslationMetadataDocument\n const client = useClient({apiVersion: `v2022-11-21`})\n const {projectId, dataset} = useWorkspace()\n const toast = useToast()\n const [invalidIds, setInvalidIds] = React.useState<string[]>([])\n\n const addId = useCallback((id: string) => {\n setInvalidIds((ids) => [...ids, id])\n }, [])\n\n const removeId = useCallback((id: string) => {\n setInvalidIds((ids) => ids.filter((i) => i !== id))\n }, [])\n\n const handleBulkPublish = useCallback(() => {\n const body = translations.map((translation) => ({documentId: translation.value._ref}))\n client\n .request({\n uri: `/publish/${projectId}/${dataset}`,\n method: 'POST',\n body,\n })\n .then((res) => {\n toast.push({\n status: 'success',\n title: 'Success',\n description: 'Bulk publish complete',\n })\n })\n .catch((err) => {\n console.error(err)\n toast.push({\n status: 'error',\n title: 'Error',\n description: 'Bulk publish failed',\n })\n })\n }, [translations, client, projectId, dataset, toast])\n\n // TODO: Hide all this if none of the documents have drafts\n return translations?.length > 0 ? (\n <Stack space={4}>\n <Stack space={3}>\n <Text weight=\"bold\" size={1}>\n Bulk publishing\n </Text>\n <Text>\n There{' '}\n {translations.length === 1 ? `is 1 document` : `are ${translations.length} documents`}.\n </Text>\n {invalidIds.length > 0 ? (\n <Text weight=\"medium\">\n {invalidIds.length === 1 ? `1 draft has` : `${invalidIds.length} drafts have`}{' '}\n validation issues that must addressed first.\n </Text>\n ) : (\n <Text>They are all valid.</Text>\n )}\n </Stack>\n <Stack space={2}>\n {translations.map((translation) => (\n <DocumentCheck\n key={translation._key}\n id={translation.value._ref}\n addId={addId}\n removeId={removeId}\n />\n ))}\n </Stack>\n <Button\n text={`Simultaneously Publish ${\n translations.length === 1 ? `1 Document` : `${translations.length} Documents`\n }`}\n onClick={handleBulkPublish}\n disabled={Boolean(invalidIds.length)}\n />\n </Stack>\n ) : null\n}\n","import React from 'react'\nimport {definePlugin, defineField} from 'sanity'\nimport {internationalizedArray} from 'sanity-plugin-internationalized-array'\nimport {Stack} from '@sanity/ui'\n\nimport metadata from './schema/translation/metadata'\nimport MenuButton from './components/MenuButton'\nimport {PluginConfig} from './types'\nimport {LanguageBadge} from './badges'\nimport {METADATA_SCHEMA_NAME} from './constants'\nimport BulkPublish from './components/BulkPublish'\n\nconst DEFAULT_CONFIG = {\n supportedLanguages: [],\n schemaTypes: [],\n languageField: `language`,\n bulkPublish: false,\n}\n\nexport const documentInternationalization = definePlugin<PluginConfig>((config) => {\n const {supportedLanguages, schemaTypes, languageField, bulkPublish} = {\n ...DEFAULT_CONFIG,\n ...config,\n }\n\n const renderLanguageFilter = (schemaType: string, documentId?: string) => {\n return (\n <MenuButton\n supportedLanguages={supportedLanguages}\n schemaType={schemaType}\n documentId={documentId ?? ``}\n languageField={languageField}\n />\n )\n }\n\n return {\n name: '@sanity/document-internationalization',\n\n // Adds:\n // - A bulk-publishing UI component to the form\n // - Will only work for projects on a compatible plan\n form: {\n components: {\n input: (props) => {\n if (\n bulkPublish &&\n props.id === 'root' &&\n props.schemaType.name === METADATA_SCHEMA_NAME\n ) {\n return (\n <Stack space={5}>\n <BulkPublish {...props} />\n {props.renderDefault(props)}\n </Stack>\n )\n }\n\n return props.renderDefault(props)\n },\n },\n },\n\n // Adds:\n // - The `Translations` dropdown to the editing form\n // - `Badges` to documents with a language value\n document: {\n unstable_languageFilter: (prev, ctx) => {\n const {schemaType, documentId} = ctx\n\n return schemaTypes.includes(schemaType)\n ? [...prev, () => renderLanguageFilter(schemaType, documentId)]\n : prev\n },\n badges: (prev, {schemaType}) => {\n if (!schemaTypes.includes(schemaType)) {\n return prev\n }\n\n return [(props) => LanguageBadge(props, supportedLanguages, languageField), ...prev]\n },\n },\n\n // Adds:\n // - The `Translations metadata` document type to the schema\n schema: {\n // Create the metadata document type\n types: [metadata(schemaTypes)],\n\n // For every schema type this plugin is enabled on\n // Create an initial value template to set the language\n templates: (prev, {schema}) => {\n const parameterizedTemplates = schemaTypes.map((schemaType) => ({\n id: `${schemaType}-parameterized`,\n title: `${schema?.get(schemaType)?.title ?? schemaType}: with Language`,\n schemaType,\n parameters: [{name: `languageId`, title: `Language ID`, type: `string`}],\n value: ({languageId}: {languageId: string}) => ({\n [languageField]: languageId,\n }),\n }))\n\n const staticTemplates = schemaTypes.flatMap((schemaType) => {\n return supportedLanguages.map((language) => ({\n id: `${schemaType}-${language.id}`,\n title: `${language.title} Lesson`,\n schemaType,\n value: {\n [languageField]: language.id,\n },\n }))\n })\n\n return [...prev, ...parameterizedTemplates, ...staticTemplates]\n },\n },\n\n // Uses:\n // - `sanity-plugin-internationalized-array` to maintain the translations array\n plugins: [\n // Translation metadata stores its references using this plugin\n // It cuts down on attribute usage and gives UI conveniences to add new translations\n internationalizedArray({\n languages: supportedLanguages,\n fieldTypes: [\n // TODO: The plugin should allow this kind of input\n // @ts-ignore\n defineField(\n {\n name: 'reference',\n type: 'reference',\n to: schemaTypes.map((type) => ({type: type})),\n // TODO: Add a validation rule to *ensure* the document's language matches the array key\n // Reference filters don't actually enforce validation!\n // validation: (Rule) => Rule.custom(),\n options: {\n collapsed: false,\n // TODO: Update type once it knows the values of this filter\n // @ts-ignore\n filter: ({parent, document}) => {\n if (!parent) return null\n\n // I'm not sure in what instance there's an array of parents\n // But the Type suggests it's possible\n const parentArray = Array.isArray(parent) ? parent : [parent]\n const language = parentArray.find((p) => p._key)\n\n if (!language?._key) return null\n\n if (document.schemaTypes) {\n return {\n filter: `_type in $schemaTypes && ${languageField} == $language`,\n params: {schemaTypes: document.schemaTypes, language: language._key},\n }\n }\n\n return {\n filter: `${languageField} == $language`,\n params: {language: language._key},\n }\n },\n },\n },\n {strict: false}\n ),\n ],\n }),\n ],\n }\n})\n","import {DocumentBadgeDescription, DocumentBadgeProps} from 'sanity'\n\nimport {Language} from '../types'\n\nexport function LanguageBadge(\n props: DocumentBadgeProps,\n supportedLanguages: Language[],\n languageField: string\n): DocumentBadgeDescription | null {\n const source = props?.draft || props?.published\n const languageId = source?.[languageField]\n const language = supportedLanguages.find((l) => l.id === languageId)\n\n if (!language) {\n return null\n }\n\n return {\n label: language.id,\n title: language.title,\n color: `primary`,\n }\n}\n"],"names":["metadata","schemaTypes","defineType","type","name","title","icon","TranslateIcon","liveEdit","fields","defineField","description","of","options","list","readOnly","_ref","value","Boolean","preview","select","translations","documentSchemaTypes","prepare","selection","length","languageKeys","map","t","_key","toUpperCase","join","subtitle","s","filter","useOpenInNewPane","id","routerContext","React","useContext","RouterContext","routerPanesState","groupIndex","usePaneRouter","useCallback","panes","splice","params","href","resolvePathFromState","navigateUrl","path","createReference","key","ref","_type","_weak","_strengthenOnPublish","LanguageOption","props","_a","index","language","languageField","schemaType","documentId","disabled","current","sourceId","sourceLanguageId","translation","client","useClient","toast","useToast","open","handleOpen","handleCreate","async","metadataExists","_id","transaction","documentIds","startsWith","replace","concat","newTranslationDocument","fetch","ids","uuid","create","metadataId","newTranslationReference","metadataPatch","patch","setIfMissing","insert","sourceReference","createIfNotExists","commit","then","push","status","catch","err","console","error","message","jsx","Button","onClick","mode","children","jsxs","Flex","gap","align","Spinner","Text","size","SplitVerticalIcon","CheckmarkIcon","AddIcon","Box","flex","Badge","tone","LanguageManage","text","CogIcon","LanguagePatch","source","handleClick","currentId","set","ChevronRightIcon","justify","MenuButton","supportedLanguages","setOpen","useState","o","button","setButton","popover","setPopover","handleClickOutside","useClickOutside","data","loading","useListeningQuery","translationSchema","useTranslationMetadata","draft","published","useEditState","sourceLanguageIsValid","some","l","content","overflow","Card","padding","Stack","space","Fragment","langIndex","find","Popover","constrainSize","portal","selected","DocumentCheck","addId","removeId","editState","validationStatus","useValidationStatus","schema","useSchema","validationHasErrors","useMemo","validation","item","level","useEffect","border","Preview","layout","get","BulkPublish","apiVersion","projectId","dataset","useWorkspace","invalidIds","setInvalidIds","i","handleBulkPublish","body","request","uri","method","res","weight","DEFAULT_CONFIG","bulkPublish","documentInternationalization","definePlugin","config","form","components","input","_objectSpread","renderDefault","document","unstable_languageFilter","prev","ctx","includes","renderLanguageFilter","badges","_ref2","languageId","label","color","LanguageBadge","types","templates","_ref3","_b","parameters","_ref4","flatMap","plugins","internationalizedArray","languages","fieldTypes","to","collapsed","_ref5","parent","Array","isArray","p","strict"],"mappings":"4gDAOA,IAAAA,EAAgBC,GACdC,EAAW,CACTC,KAAM,WACNC,KCVgC,uBDWhCC,MAAO,uBACPC,KAAMC,EACNC,UAAU,EACVC,OAAQ,CACNC,EAAY,CACVN,KAAM,eACND,KAAM,oCAERO,EAAY,CACVN,KAAM,cACNO,YACE,sFACFR,KAAM,QACNS,GAAI,CAAC,CAACT,KAAM,WACZU,QAAS,CAACC,KAAMb,GAChBc,SAAUC,IAAA,IAACC,MAACA,GAAKD,EAAA,OAAME,QAAQD,EAAK,KAGxCE,QAAS,CACPC,OAAQ,CACNC,aAAc,eACdC,oBAAqB,eAEvBC,QAAQC,GACA,MAAAH,aAACA,EAAcC,oBAAAA,GAAuBE,EACtCnB,EACoB,IAAxBgB,EAAaI,OAAoCJ,gBAAAA,GAAAA,OAAAA,EAAaI,OAAA,iBAC1DC,EAAeL,EAAaI,OAC9BJ,EAAaM,KAAKC,GAAsBA,EAAEC,KAAKC,gBAAeC,KAAK,MACnE,GAUG,MAAA,CACL1B,QACA2B,SAXe,CACfN,aAAmBA,EAAkB,KAAA,MAChB,MAArBJ,OAAqB,EAAAA,EAAAG,QACjBH,EAAoBK,KAAKM,GAAcA,EAAEH,gBAAeC,WACxD,sBAEHG,OAAOhB,SACPa,KAAQ,KAMb,KElDU,SAAAI,EAAiBC,EAAajC,GACtC,MAAAkC,EAAgBC,EAAMC,WAAWC,IACjCC,iBAACA,EAAAC,WAAkBA,GAAcC,IAmBhC,OAjBeL,EAAMM,aAAY,KACtC,IAAKP,IAAkBD,IAAOjC,EAC5B,OAGI,MAAA0C,EAAQ,IAAIJ,GACZI,EAAAC,OAAOJ,EAAa,EAAG,EAAG,CAC9B,CACEN,KACAW,OAAQ,CAAC5C,WAIb,MAAM6C,EAAOX,EAAcY,qBAAqB,CAACJ,UACjDR,EAAca,YAAY,CAACC,KAAMH,GAAK,GACrC,CAACZ,EAAIjC,EAAMkC,EAAeI,EAAkBC,GAGjD,CCFA,SAASU,EAAgBC,EAAaC,EAAanD,GAC1C,MAAA,CACL0B,KAAMwB,EACNpC,MAAO,CACLsC,MAAO,YACPvC,KAAMsC,EACNE,OAAO,EACPC,qBAAsB,CACpBtD,SAIR,CAEA,SAAwBuD,EAAeC,GAtCvC,IAAAC,EAuCQ,MAAAC,MACJA,EAAAC,SACAA,EAAAC,cACAA,EAAAC,WACAA,EAAAC,WACAA,EAAAC,SACAA,EAAAC,QACAA,EAAAC,SACAA,EAAAC,iBACAA,EAAArE,SACAA,EAAAsE,YACAA,GACEX,EACEY,EAASC,IACTC,EAAQC,IAERC,EAAOxC,EAAiB,OAAAyB,EAAA,MAAAU,OAAA,EAAAA,EAAarD,YAAb,EAAA2C,EAAoB5C,KAAMgD,GAClDY,EAAahC,GAAY,IAAM+B,KAAQ,CAACA,IAExCE,EAAejC,GAAYkC,UA1DnClB,IAAAA,EA2DU,MAAAmB,EAAiB7D,QAAQ,MAAAlB,OAAA,EAAAA,EAAUgF,KACnCC,EAAcV,EAAOU,cAKrBC,EAAcjB,EAAWkB,WAAoB,WAC/C,CAAClB,EAAYA,EAAWmB,uBACxB,CAACnB,EAAA,UAAAoB,OAAsBpB,IAIrBqB,eAHuBf,EAAOgB,MAAkD,2CAAA,CACpFC,IAAKN,KAGF,CAAA,EAAA,CACHF,IAAA,UAAAK,OAAeI,KACf1B,CAACA,GAAgBD,EAAS1B,KAG5B6C,EAAYS,OAAOJ,GAEnB,MAAMK,EAAa,OAAA/B,EAAA,MAAA5D,OAAA,EAAAA,EAAUgF,KAAVpB,EAAiB6B,IAC9BG,EAA0BxC,EAC9BU,EAAS1B,GACTkD,EAAuBN,IAAII,QAAqB,UAAA,IAChDpB,GAIF,GAAIe,EAAgB,CACZ,MAAA5B,EAAA,gBAAAkC,OAAuBxB,EAAQ,EAAA,KAC/BgC,EAAgBtB,EACnBuB,MAAMH,GACNI,aAAa,CAAC1E,aAAc,KAC5B2E,OAAA,SAAiB7C,EAAM,CAACyC,IAE3BX,EAAYa,MAAMD,EAAa,KAC1B,CAEL,MAAMI,EAAkB5B,EACpBjB,EAAgBiB,EAAkBD,EAAUJ,GAC5C,KAEJiB,EAAYiB,kBAAkB,CAC5BlB,IAAKW,EACLpC,MFvG4B,uBEwG5BtD,YAAa,CAAC+D,GACd3C,aAAc,CAACuE,EAAyBK,GAAiB/D,OAAOhB,UAEpE,CAGG+D,EAAAkB,SACAC,MAAK,IAEG3B,EAAM4B,KAAK,CAChBC,OAAQ,UACRjG,MAAkByD,WAAAA,OAAAA,EAASzD,MAAA,gBAC3BM,YAAaoE,sEAKhBwB,OAAOC,IACNC,QAAQC,MAAMF,GAEP/B,EAAM4B,KAAK,CAChBC,OAAQ,QACRjG,MAAO,6BACPM,YAAa6F,EAAIG,YAEpB,GACF,CACDpC,EACAN,EACAJ,EACAC,EACAC,EACU,MAAV/D,OAAU,EAAAA,EAAAgF,IACVhB,EACAI,EACAC,EACAI,IAGF,OACGmC,EAAAC,EAAA,CACCC,QAASxC,EAAcM,EAAaC,EACpCkC,KAAM5C,EAAsB,UAAA,QAC5BD,SAAUA,GAAYC,EAEtB6C,SAACC,EAAAC,EAAA,CAAKC,IAAK,EAAGC,MAAM,SACjBJ,SAAA,CACC9C,EAAA0C,EAACS,EAAQ,CAAA,GAERT,EAAAU,EAAA,CAAKC,KAAM,EAETP,WAAA1C,EAAekD,EAAuBrD,EAAWsD,EAAoBC,EAApC,CAAA,KAGrCd,EAAAe,EAAA,CAAIC,KAAM,EACTZ,SAACJ,EAAAU,EAAA,CAAMN,SAASlD,EAAAzD,UAEjBuG,EAAAiB,EAAA,CAAMC,KAAM5D,GAAYC,EAAsB,UAAA,UAAY6C,SAASlD,EAAA1B,SAI5E,CC1JA,SAAwB2F,EAAepE,GAC/B,MAAAvB,GAACA,GAAMuB,EACPgB,EAAOxC,EAAiBC,EHbI,wBGelC,OACGwE,EAAAC,EAAA,CACC3C,UAAW9B,EACX2E,KAAK,QACLiB,KAAK,sBACL1H,KAAM2H,EACNnB,QAAS,IAAMnC,KAGrB,CCRA,SAAwBuD,EAAcvE,GAC9B,MAAAG,SAACA,gBAAUC,EAAeE,WAAAA,EAAAD,WAAYA,SAAYmE,EAAQjE,SAAAA,GAAW,GAASP,EAC9EY,EAASC,IACTC,EAAQC,IAER0D,EAAc9F,EAAMM,aAAY,KACpC,MAAMyF,EAAYF,EAASA,EAAOnD,IAAef,SAAAA,OAAAA,GAC3CgB,EAAcV,EAAOU,cAEtBkD,GACHlD,EAAYiB,kBAAkB,CAC5BlB,IAAKqD,EACL9E,MAAOS,IAIL,MAAA8B,EAAQvB,EAAOuB,MAAMuC,GAAWC,IAAI,CAACvE,CAACA,GAAgBD,EAAS1B,KACrE6C,EAAYa,MAAMA,GAGfb,EAAAkB,SACAC,MAAK,KACJ3B,EAAM4B,KAAK,CACThG,MAAmCyD,4BAAAA,OAAAA,EAASzD,OAC5CiG,OAAQ,WACT,IAEFC,OAAOC,IACNC,QAAQC,MAAMF,GAEP/B,EAAM4B,KAAK,CAChBhG,MAA6CyD,sCAAAA,OAAAA,EAASzD,OACtDiG,OAAQ,YAEX,GACF,CAAC6B,EAAQlE,EAAYM,EAAQR,EAAeD,EAAUE,EAAYS,IAErE,OACGmC,EAAAC,EAAA,CACCE,KAAK,QACLiB,KAAMlE,EAASzD,MACfC,KAAMiI,EACNzB,QAAS,IAAMsB,IACflE,WACAsE,QAAQ,cAGd,CC7CA,SAAwBC,EAAW9E,GACjC,MAAM+E,mBAACA,EAAA1E,WAAoBA,EAAYC,WAAAA,EAAAF,cAAYA,GAAiBJ,GAE7DgB,EAAMgE,GAAWC,GAAS,GAC3BR,EAAcxF,GAAY,IAAM+F,GAASE,IAAOA,KAAI,KACnDC,EAAQC,GAAaH,EAA6B,OAClDI,EAASC,GAAcL,EAA6B,MACrDM,EAAqBtG,GAAY,IAAM+F,GAAQ,IAAQ,IAC7DQ,EAAgBD,EAAoB,CAACJ,EAAQE,IACvC,MAACI,KAAMpJ,EAAUqJ,QAAAA,EAAA3C,MAASA,GCrBlB,SACdtE,EACA4B,GAMA,MACMoF,KAACA,EAAMC,QAAAA,EAAA3C,MAASA,GAAS4C,EADjB,wEACoD,CAChEvG,OAAQ,CAACX,KAAImH,kBNhBmB,0BMmB3B,MAAA,CAACH,OAAMC,UAAS3C,QACzB,CDO2C8C,CAAuBvF,IAC1DwF,MAACA,EAAOC,UAAAA,GAAaC,EAAa1F,EAAYD,GAC9CmE,EAASsB,GAASC,EAElBrF,EAA4B,MAAT8D,OAAS,EAAAA,EAAApE,GAC5B6F,EAAwBlB,EAAmBmB,MAAMC,GAAMA,EAAE1H,KAAOiC,IAEhE0F,EACHnD,EAAAe,EAAA,CAAIqC,SAAS,OACXhD,WACEJ,EAAAqD,EAAA,CAAKnC,KAAK,WAAWoC,QAAS,EAC7BlD,SAACC,EAAAK,EAAA,CAAKN,SAAA,CAAA,UAAQN,OAGfO,EAAAkD,EAAA,CAAMD,QAAS,EAAGE,MAAO,EACvBpD,SAAA,CAAA0B,EAAmBjH,OAAS,EAC3BwF,EAAAoD,EAAA,CACGrD,SAAA,CAAmB0B,EAAA/G,KAAI,CAACmC,EAAUwG,KA5CjD,IAAA1G,EA6CiB,OAAAyF,GAAWhF,GAAoBuF,EAG7BhD,EAAAlD,EAAA,CAECG,MAAOyG,EACPxG,WACAC,gBACAC,aACAC,aACAC,SAAUmF,EACVlF,QAASL,EAAS1B,KAAOiC,EACzBrE,WACAoE,SAAUH,EACVI,mBACAC,kBAAatE,WAAUqB,aAAakJ,MAAM3I,GAAMA,EAAEC,OAASiC,EAAS1B,MAX/D0B,EAAS1B,IAefwE,EAAAsB,EAAA,CAECnE,gBACAoE,SACAlE,aACAD,aACAF,WAIAI,SACE,OAAAN,EAAA,MAAA5D,OAAA,EAAAA,EAAUqB,aACPa,QAAQN,IA5EjCgC,IAAAA,EA4EuC,OAAA,OAAAA,EAAA,MAAAhC,OAAA,EAAAA,EAAGX,YAAH,EAAA2C,EAAU5C,QAASiD,CAAA,IACjC4F,MAAMjI,GAAMA,EAAEC,OAASiC,EAAS1B,OAAOwB,GAZvCE,EAAS1B,GAchB,IAIHiH,EAAU,KACTpC,EAAAoD,EAAA,CAEGrD,SAAA,CAAA3C,EAAmB,KACjBuC,EAAAqD,EAAA,CAAKnC,KAAK,UAAUoC,QAAS,EAC5BlD,SAACC,EAAAK,EAAA,CAAKC,KAAM,EAAGP,SAAA,CAAA,0BACS,KAAG,IAAE,YACjBJ,EAAA,SAAA,CAAOI,SAAA,uBAKtB3C,IAAqBuF,EACnBhD,EAAAqD,EAAA,CAAKnC,KAAK,UAAUoC,QAAS,EAC5BlD,SAACC,EAAAK,EAAA,CAAKC,KAAM,EAAGP,SAAA,CAAA,qCACsBJ,EAAA,OAAA,CAAMI,SAAA3C,MACxC,KAAG,IAAE,yCAIR,WAIR,KACHuC,EAAAmB,EAAA,CAAe3F,GAAc,MAAVpC,OAAU,EAAAA,EAAAgF,WAMtC,OACG4B,EAAA4D,EAAA,CAAQC,eAAa,EAACV,UAAkBpF,OAAY+F,QAAM,EAACpH,IAAK2F,EAC/DjC,SAACJ,EAAAC,EAAA,CACCmB,KAAK,eACLjB,KAAK,QACL7C,UAAWiE,EACXL,MACGK,IAAYkB,GAAWhF,GAAoBuF,OAAyB,EAAY,UAEnFtJ,KAAMC,EACNuG,QAASsB,EACT9E,IAAKyF,EACL4B,SAAUhG,KAIlB,CE/GA,SAAwBiG,EAAcjH,GACpC,MAAMvB,GAACA,EAAAyI,MAAIA,EAAOC,SAAAA,GAAYnH,EACxBoH,EAAYpB,EAAavH,EAAM,IAC/B4I,EAAmBC,EAAoB7I,EAAM,IAC7C8I,EAASC,IAETC,EAAsB9I,EAAM+I,SAAQ,IAEtCL,EAAiBM,WAAW7J,OAAS,GACrCuJ,EAAiBM,WAAWf,MAAMgB,GAAwB,UAAfA,EAAKC,SAEjD,CAACR,IAWA,OATJ1I,EAAMmJ,WAAU,KACVL,EACFP,EAAMzI,GAEN0I,EAAS1I,EACX,GACC,CAACyI,EAAOzI,EAAI0I,EAAUM,IAGpBL,EAAUtB,MAKZ7C,EAAAqD,EAAA,CAAKyB,QAAM,EAACxB,QAAS,EAAGpC,KAAMsD,EAAmC,WAAA,WAC/DpE,SAAA+D,EAAUrB,UACR9C,EAAA+E,EAAA,CACCC,OAAO,UACP3K,MAAO8J,EAAUrB,UACjB1F,WAAYkH,EAAOW,IAAId,EAAUrB,UAAUnG,WAG5C8D,EAAQ,MAZN,IAgBX,CCtCA,SAAwByE,EAAYnI,GAC5B,MAAAtC,aAACA,GAAgBsC,EAAM1C,MACvBsD,EAASC,EAAU,CAACuH,WAAA,iBACpBC,UAACA,EAAAC,QAAWA,GAAWC,IACvBzH,EAAQC,KACPyH,EAAYC,GAAiB9J,EAAMsG,SAAmB,IAEvDiC,EAAQjI,GAAaR,IACzBgK,GAAe5G,GAAQ,IAAIA,EAAKpD,IAAG,GAClC,IAEG0I,EAAWlI,GAAaR,IACdgK,GAAC5G,GAAQA,EAAItD,QAAQmK,GAAMA,IAAMjK,KAAG,GACjD,IAEGkK,EAAoB1J,GAAY,KAC9B,MAAA2J,EAAOlL,EAAaM,KAAK2C,IAAiB,CAACL,WAAYK,EAAYrD,MAAMD,SAC/EuD,EACGiI,QAAQ,CACPC,IAAiBT,YAAAA,OAAAA,EAAaC,KAAAA,OAAAA,GAC9BS,OAAQ,OACRH,SAEDnG,MAAMuG,IACLlI,EAAM4B,KAAK,CACTC,OAAQ,UACRjG,MAAO,UACPM,YAAa,yBACd,IAEF4F,OAAOC,IACNC,QAAQC,MAAMF,GACd/B,EAAM4B,KAAK,CACTC,OAAQ,QACRjG,MAAO,QACPM,YAAa,uBACd,GACF,GACF,CAACU,EAAckD,EAAQyH,EAAWC,EAASxH,IAGvC,OAAA,MAAApD,OAAA,EAAAA,EAAcI,QAAS,EAC3BwF,EAAAkD,EAAA,CAAMC,MAAO,EACZpD,SAAA,CAACC,EAAAkD,EAAA,CAAMC,MAAO,EACZpD,SAAA,CAACJ,EAAAU,EAAA,CAAKsF,OAAO,OAAOrF,KAAM,EAAGP,SAAA,oBAG5BC,EAAAK,EAAA,CAAKN,SAAA,CAAA,QACE,IACmB,IAAxB3F,EAAaI,OAAwCJ,gBAAAA,OAAAA,OAAAA,EAAaI,OAAA,cAAmB,OAEvF0K,EAAW1K,OAAS,EAClBwF,EAAAK,EAAA,CAAKsF,OAAO,SACV5F,SAAA,CAAsB,IAAtBmF,EAAW1K,OAAkC0K,cAAAA,GAAAA,OAAAA,EAAW1K,OAAA,gBAAsB,IAAI,kDAIpFmF,EAAAU,EAAA,CAAKN,SAAA,2BAGTJ,EAAAuD,EAAA,CAAMC,MAAO,EACXpD,SAAa3F,EAAAM,KAAK2C,GAChBsC,EAAAgE,EAAA,CAECxI,GAAIkC,EAAYrD,MAAMD,KACtB6J,QACAC,YAHKxG,EAAYzC,UAOtB+E,EAAAC,EAAA,CACCmB,sCAC0B,IAAxB3G,EAAaI,OAAe,aAAA,GAAA4D,OAAkBhE,EAAaI,OAAA,eAE7DqF,QAASwF,EACTpI,SAAUhD,QAAQiL,EAAW1K,aAG/B,IACN,CCvFA,MAAMoL,EAAiB,CACrBnE,mBAAoB,GACpBzI,YAAa,GACb8D,cAAe,WACf+I,aAAa,GAGFC,EAA+BC,GAA4BC,IACtE,MAAMvE,mBAACA,EAAAzI,YAAoBA,EAAa8D,cAAAA,EAAA+I,YAAeA,GAClDD,EAAAA,EAAAA,CAAAA,EAAAA,GACAI,GAcE,MAAA,CACL7M,KAAM,wCAKN8M,KAAM,CACJC,WAAY,CACVC,MAAQzJ,GAEJmJ,GACa,SAAbnJ,EAAMvB,IT/CkB,yBSgDxBuB,EAAMK,WAAW5D,KAGd6G,EAAAkD,EAAA,CAAMC,MAAO,EACZpD,SAAA,CAACJ,EAAAkF,EAAAuB,EAAA,CAAA,EAAgB1J,IAChBA,EAAM2J,cAAc3J,MAKpBA,EAAM2J,cAAc3J,KAQjC4J,SAAU,CACRC,wBAAyB,CAACC,EAAMC,KACxB,MAAA1J,WAACA,EAAYC,WAAAA,GAAcyJ,EAEjC,OAAOzN,EAAY0N,SAAS3J,GACxB,IAAIyJ,EAAM,IA9CS,EAACzJ,EAAoBC,IAE7C2C,EAAA6B,EAAA,CACCC,qBACA1E,aACAC,WAA0B,MAAdA,EAAcA,EAAA,GAC1BF,kBAwCoB6J,CAAqB5J,EAAYC,IACjDwJ,CAAA,EAENI,OAAQ,CAACJ,EAAuBK,KAAA,IAAjB9J,WAACA,GAAgB8J,EAC9B,OAAK7N,EAAY0N,SAAS3J,GAInB,CAAEL,GC3ED,SACdA,EACA+E,EACA3E,GAEM,MAAAoE,GAAgB,MAAPxE,OAAO,EAAAA,EAAA8F,SAAgB,MAAP9F,OAAO,EAAAA,EAAA+F,WAChCqE,EAAsB,MAAT5F,OAAS,EAAAA,EAAApE,GACtBD,EAAW4E,EAAmB6B,MAAMT,GAAMA,EAAE1H,KAAO2L,IAEzD,OAAKjK,EAIE,CACLkK,MAAOlK,EAAS1B,GAChB/B,MAAOyD,EAASzD,MAChB4N,MAAO,WANA,IAQX,CDyD2BC,CAAcvK,EAAO+E,EAAoB3E,MAAmB0J,GAHtEA,CAG0E,GAMvFvC,OAAQ,CAENiD,MAAO,CAACnO,EAASC,IAIjBmO,UAAW,CAACX,EAAmBY,KAAA,IAAbnD,OAACA,GAAYmD,EAsB7B,MAAO,IAAIZ,KArBoBxN,EAAY0B,KAAKqC,IA5FxD,IAAAJ,EAAA0K,EA4FwE,MAAA,CAC9DlM,aAAO4B,EAAA,kBACP3D,MAAU,GAAAgF,OAAA,OAAAiJ,EAAA,OAAA1K,EAAA,MAAAsH,OAAA,EAAAA,EAAQW,IAAI7H,SAAZ,EAAAJ,EAAyBvD,OAASiO,EAAAtK,EAAA,mBAC5CA,aACAuK,WAAY,CAAC,CAACnO,kBAAoBC,MAAO,cAAeF,KAAM,WAC9Dc,MAAOuN,IAAA,IAACT,WAACA,GAAuCS,EAAA,MAAA,CAC9CzK,CAACA,GAAgBgK,EACnB,EACF,OAEwB9N,EAAYwO,SAASzK,GACpC0E,EAAmB/G,KAAKmC,IAAc,CAC3C1B,aAAO4B,EAAA,KAAAqB,OAAcvB,EAAS1B,IAC9B/B,MAAUyD,GAAAA,OAAAA,EAASzD,MAAA,WACnB2D,aACA/C,MAAO,CACL8C,CAACA,GAAgBD,EAAS1B,UAK8B,GAMlEsM,QAAS,CAGPC,EAAuB,CACrBC,UAAWlG,EACXmG,WAAY,CAGVnO,EACE,CACEN,KAAM,YACND,KAAM,YACN2O,GAAI7O,EAAY0B,KAAKxB,IAAU,CAACA,WAIhCU,QAAS,CACPkO,WAAW,EAGX7M,OAAQ8M,IAAwB,IAAvBC,OAACA,EAAA1B,SAAQA,GAAcyB,EAC9B,IAAKC,EAAe,OAAA,KAIpB,MACMnL,GADcoL,MAAMC,QAAQF,GAAUA,EAAS,CAACA,IACzB1E,MAAM6E,GAAMA,EAAEvN,OAE3C,OAAe,MAAViC,OAAU,EAAAA,EAAAjC,MAEX0L,EAAStN,YACJ,CACLiC,0CAAoC6B,EAAA,iBACpChB,OAAQ,CAAC9C,YAAasN,EAAStN,YAAa6D,SAAUA,EAASjC,OAI5D,CACLK,iBAAW6B,EAAA,iBACXhB,OAAQ,CAACe,SAAUA,EAASjC,OAXF,IAY5B,IAIN,CAACwN,QAAQ,QAKnB"}
package/lib/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";function e(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function t(t){for(var n=1;n<arguments.length;n++){var s=null!=arguments[n]?arguments[n]:{};n%2?e(Object(s),!0).forEach((function(e){a(t,e,s[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(s)):e(Object(s)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(s,e))}))}return t}function a(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}Object.defineProperty(exports,"__esModule",{value:!0});var n=require("react/jsx-runtime"),s=require("sanity"),r=require("sanity-plugin-internationalized-array"),i=require("@sanity/ui"),l=require("@sanity/icons"),o=require("react"),c=require("@sanity/uuid"),u=require("sanity/desk"),d=require("sanity/router"),p=require("sanity-plugin-utils");function h(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var g=h(o);var m=e=>s.defineType({type:"document",name:"translation.metadata",title:"Translation metadata",icon:l.TranslateIcon,liveEdit:!0,fields:[s.defineField({name:"translations",type:"internationalizedArrayReference"}),s.defineField({name:"schemaTypes",description:"Used to filter the reference fields above so all translations share the same types.",type:"array",of:[{type:"string"}],options:{list:e},readOnly:e=>{let{value:t}=e;return Boolean(t)}})],preview:{select:{translations:"translations",documentSchemaTypes:"schemaTypes"},prepare(e){const{translations:t,documentSchemaTypes:a}=e,n=1===t.length?"1 Translation":"".concat(t.length," Translations"),s=t.length?t.map((e=>e._key.toUpperCase())).join(", "):"";return{title:n,subtitle:[s?"(".concat(s,")"):null,(null==a?void 0:a.length)?a.map((e=>e.toUpperCase())).join(", "):"No Schemas Defined"].filter(Boolean).join(" ")}}}});function f(e,t){const a=g.default.useContext(d.RouterContext),{routerPanesState:n,groupIndex:s}=u.usePaneRouter();return g.default.useCallback((()=>{if(!a||!e||!t)return;const r=[...n];r.splice(s+1,0,[{id:e,params:{type:t}}]);const i=a.resolvePathFromState({panes:r});a.navigateUrl({path:i})}),[e,t,a,n,s])}function y(e,t,a){return{_key:e,value:{_type:"reference",_ref:t,_weak:!0,_strengthenOnPublish:{type:a}}}}function x(e){var a;const{index:r,language:u,languageField:d,schemaType:p,documentId:h,disabled:g,current:m,sourceId:x,sourceLanguageId:b,metadata:j,translation:v}=e,T=s.useClient(),k=i.useToast(),_=f(null==(a=null==v?void 0:v.value)?void 0:a._ref,p),C=o.useCallback((()=>_()),[_]),I=o.useCallback((async()=>{var e;const a=Boolean(null==j?void 0:j._id),n=T.transaction(),s=h.startsWith("drafts.")?[h,h.replace("drafts.","")]:[h,"drafts.".concat(h)],i=t(t({},await T.fetch("*[_id in $ids]|order(_updatedAt desc)[0]",{ids:s})),{},{_id:"drafts.".concat(c.uuid()),[d]:u.id});n.create(i);const l=null!=(e=null==j?void 0:j._id)?e:c.uuid(),o=y(u.id,i._id.replace("drafts.",""),p);if(a){const e="translations[".concat(r-1,"]"),t=T.patch(l).setIfMissing({translations:[]}).insert("before",e,[o]);n.patch(t)}else{const e=b?y(b,x,p):null;n.createIfNotExists({_id:l,_type:"translation.metadata",schemaTypes:[p],translations:[o,e].filter(Boolean)})}n.commit().then((()=>k.push({status:"success",title:"Created ".concat(u.title," translation"),description:a?"Updated Translations Metadata":"Created Translations Metadata"}))).catch((e=>(console.error(e),k.push({status:"error",title:"Error creating translation",description:e.message}))))}),[T,h,r,u,d,null==j?void 0:j._id,p,x,b,k]);return n.jsx(i.Button,{onClick:v?C:I,mode:m?"default":"bleed",disabled:g||m,children:n.jsxs(i.Flex,{gap:3,align:"center",children:[g?n.jsx(i.Spinner,{}):n.jsx(i.Text,{size:2,children:v?n.jsx(l.SplitVerticalIcon,{}):m?n.jsx(l.CheckmarkIcon,{}):n.jsx(l.AddIcon,{})}),n.jsx(i.Box,{flex:1,children:n.jsx(i.Text,{children:u.title})}),n.jsx(i.Badge,{tone:g||m?"default":"primary",children:u.id})]})})}function b(e){const{id:t}=e,a=f(t,"translation.metadata");return n.jsx(i.Button,{disabled:!t,mode:"ghost",text:"Manage Translations",icon:l.CogIcon,onClick:()=>a()})}function j(e){const{language:t,languageField:a,documentId:r,schemaType:o,source:c,disabled:u=!1}=e,d=s.useClient(),p=i.useToast(),h=g.default.useCallback((()=>{const e=c?c._id:"draft.".concat(r),n=d.transaction();c||n.createIfNotExists({_id:e,_type:o});const s=d.patch(e).set({[a]:t.id});n.patch(s),n.commit().then((()=>{p.push({title:"Set document language to ".concat(t.title),status:"success"})})).catch((e=>(console.error(e),p.push({title:"Failed to set document language to ".concat(t.title),status:"error"}))))}),[c,r,d,a,t,o,p]);return n.jsx(i.Button,{mode:"ghost",text:t.title,icon:l.ChevronRightIcon,onClick:()=>h(),disabled:u,justify:"flex-start"})}function v(e){const{supportedLanguages:t,schemaType:a,documentId:r,languageField:c}=e,[u,d]=o.useState(!1),h=o.useCallback((()=>d((e=>!e))),[]),[g,m]=o.useState(null),[f,y]=o.useState(null),v=o.useCallback((()=>d(!1)),[]);i.useClickOutside(v,[g,f]);const{data:T,loading:k,error:_}=function(e,t){const{data:a,loading:n,error:s}=p.useListeningQuery("*[_type == $translationSchema && $id in translations[].value._ref][0]",{params:{id:e,translationSchema:"translation.metadata"}});return{data:a,loading:n,error:s}}(r),{draft:C,published:I}=s.useEditState(r,a),S=C||I,O=null==S?void 0:S[c],P=t.some((e=>e.id===O)),F=n.jsx(i.Box,{overflow:"auto",children:_?n.jsx(i.Card,{tone:"critical",padding:2,children:n.jsxs(i.Text,{children:["Error: ",_]})}):n.jsxs(i.Stack,{padding:1,space:1,children:[t.length>0?n.jsxs(n.Fragment,{children:[t.map(((e,t)=>{var s;return!k&&O&&P?n.jsx(x,{index:t,language:e,languageField:c,schemaType:a,documentId:r,disabled:k,current:e.id===O,metadata:T,sourceId:r,sourceLanguageId:O,translation:null==T?void 0:T.translations.find((t=>t._key===e.id))},e.id):n.jsx(j,{languageField:c,source:S,documentId:r,schemaType:a,language:e,disabled:null!=(s=null==T?void 0:T.translations.filter((e=>{var t;return(null==(t=null==e?void 0:e.value)?void 0:t._ref)!==r})).some((t=>t._key===e.id)))&&s},e.id)})),k?null:n.jsxs(n.Fragment,{children:[O?null:n.jsx(i.Card,{tone:"caution",padding:3,children:n.jsxs(i.Text,{size:1,children:["Choose a language to ",n.jsx("br",{}),"apply to ",n.jsx("strong",{children:"this Document"})]})}),O&&!P?n.jsx(i.Card,{tone:"caution",padding:3,children:n.jsxs(i.Text,{size:1,children:["Change the current language value ",n.jsx("code",{children:O}),n.jsx("br",{}),"to one of the supported languages"]})}):null]})]}):null,n.jsx(b,{id:null==T?void 0:T._id})]})});return n.jsx(i.Popover,{constrainSize:!0,content:F,open:u,portal:!0,ref:y,children:n.jsx(i.Button,{text:"Translations",mode:"bleed",disabled:!S,tone:!S||!k&&O&&P?void 0:"caution",icon:l.TranslateIcon,onClick:h,ref:m,selected:u})})}function T(e){const{id:t,addId:a,removeId:r}=e,l=s.useEditState(t,""),o=s.useValidationStatus(t,""),c=s.useSchema(),u=g.default.useMemo((()=>o.validation.length>0&&o.validation.find((e=>"error"===e.level))),[o]);return g.default.useEffect((()=>{u?a(t):r(t)}),[a,t,r,u]),l.draft?n.jsx(i.Card,{border:!0,padding:2,tone:u?"critical":"positive",children:l.published?n.jsx(s.SanityPreview,{layout:"default",value:l.published,schemaType:c.get(l.published._type)}):n.jsx(i.Spinner,{})}):null}function k(e){const{translations:t}=e.value,a=s.useClient({apiVersion:"v2022-11-21"}),{projectId:r,dataset:l}=s.useWorkspace(),c=i.useToast(),[u,d]=g.default.useState([]),p=o.useCallback((e=>{d((t=>[...t,e]))}),[]),h=o.useCallback((e=>{d((t=>t.filter((t=>t!==e))))}),[]),m=o.useCallback((()=>{const e=t.map((e=>({documentId:e.value._ref})));a.request({uri:"/publish/".concat(r,"/").concat(l),method:"POST",body:e}).then((e=>{c.push({status:"success",title:"Success",description:"Bulk publish complete"})})).catch((e=>{console.error(e),c.push({status:"error",title:"Error",description:"Bulk publish failed"})}))}),[t,a,r,l,c]);return(null==t?void 0:t.length)>0?n.jsxs(i.Stack,{space:4,children:[n.jsxs(i.Stack,{space:3,children:[n.jsx(i.Text,{weight:"bold",size:1,children:"Bulk publishing"}),n.jsxs(i.Text,{children:["There"," ",1===t.length?"is 1 document":"are ".concat(t.length," documents"),"."]}),u.length>0?n.jsxs(i.Text,{weight:"medium",children:[1===u.length?"1 draft has":"".concat(u.length," drafts have")," ","validation issues that must addressed first."]}):n.jsx(i.Text,{children:"They are all valid."})]}),n.jsx(i.Stack,{space:2,children:t.map((e=>n.jsx(T,{id:e.value._ref,addId:p,removeId:h},e._key)))}),n.jsx(i.Button,{text:"Simultaneously Publish ".concat(1===t.length?"1 Document":"".concat(t.length," Documents")),onClick:m,disabled:Boolean(u.length)})]}):null}const _={supportedLanguages:[],schemaTypes:[],languageField:"language",bulkPublish:!1},C=s.definePlugin((e=>{const{supportedLanguages:a,schemaTypes:l,languageField:o,bulkPublish:c}=t(t({},_),e);return{name:"@sanity/document-internationalization",form:{components:{input:e=>c&&"root"===e.id&&"translation.metadata"===e.schemaType.name?n.jsxs(i.Stack,{space:5,children:[n.jsx(k,t({},e)),e.renderDefault(e)]}):e.renderDefault(e)}},document:{unstable_languageFilter:(e,t)=>{const{schemaType:s,documentId:r}=t;return l.includes(s)?[...e,()=>((e,t)=>n.jsx(v,{supportedLanguages:a,schemaType:e,documentId:null!=t?t:"",languageField:o}))(s,r)]:e},badges:(e,t)=>{let{schemaType:n}=t;return l.includes(n)?[e=>function(e,t,a){const n=(null==e?void 0:e.draft)||(null==e?void 0:e.published),s=null==n?void 0:n[a],r=t.find((e=>e.id===s));return r?{label:r.id,title:r.title,color:"primary"}:null}(e,a,o),...e]:e}},schema:{types:[m(l)],templates:(e,t)=>{let{schema:n}=t;return[...e,...l.map((e=>{var t,a;return{id:"".concat(e,"-parameterized"),title:"".concat(null!=(a=null==(t=null==n?void 0:n.get(e))?void 0:t.title)?a:e,": with Language"),schemaType:e,parameters:[{name:"languageId",title:"Language ID",type:"string"}],value:e=>{let{languageId:t}=e;return{[o]:t}}}})),...l.flatMap((e=>a.map((t=>({id:"".concat(e,"-").concat(t.id),title:"".concat(t.title," Lesson"),schemaType:e,value:{[o]:t.id}})))))]}},plugins:[r.internationalizedArray({languages:a,fieldTypes:[s.defineField({name:"reference",type:"reference",to:l.map((e=>({type:e}))),options:{collapsed:!1,filter:e=>{let{parent:t,document:a}=e;var n;if(!t)return null;const s=!(null==(n=(Array.isArray(t)?t:[t]).find((e=>e._key)))?void 0:n._key);return s?a.schemaTypes?{filter:"_type in $schemaTypes && ".concat(o," == $language"),params:{schemaTypes:a.schemaTypes,language:s}}:{filter:"".concat(o," == $language"),params:{language:s}}:null}}},{strict:!1})]})]}}));exports.documentInternationalization=C;
1
+ "use strict";function e(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function t(t){for(var n=1;n<arguments.length;n++){var s=null!=arguments[n]?arguments[n]:{};n%2?e(Object(s),!0).forEach((function(e){a(t,e,s[e])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(s)):e(Object(s)).forEach((function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(s,e))}))}return t}function a(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}Object.defineProperty(exports,"__esModule",{value:!0});var n=require("react/jsx-runtime"),s=require("sanity"),r=require("sanity-plugin-internationalized-array"),i=require("@sanity/ui"),l=require("@sanity/icons"),o=require("react"),c=require("@sanity/uuid"),u=require("sanity/desk"),d=require("sanity/router"),p=require("sanity-plugin-utils");function h(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var g=h(o);var m=e=>s.defineType({type:"document",name:"translation.metadata",title:"Translation metadata",icon:l.TranslateIcon,liveEdit:!0,fields:[s.defineField({name:"translations",type:"internationalizedArrayReference"}),s.defineField({name:"schemaTypes",description:"Used to filter the reference fields above so all translations share the same types.",type:"array",of:[{type:"string"}],options:{list:e},readOnly:e=>{let{value:t}=e;return Boolean(t)}})],preview:{select:{translations:"translations",documentSchemaTypes:"schemaTypes"},prepare(e){const{translations:t,documentSchemaTypes:a}=e,n=1===t.length?"1 Translation":"".concat(t.length," Translations"),s=t.length?t.map((e=>e._key.toUpperCase())).join(", "):"";return{title:n,subtitle:[s?"(".concat(s,")"):null,(null==a?void 0:a.length)?a.map((e=>e.toUpperCase())).join(", "):"No Schemas Defined"].filter(Boolean).join(" ")}}}});function f(e,t){const a=g.default.useContext(d.RouterContext),{routerPanesState:n,groupIndex:s}=u.usePaneRouter();return g.default.useCallback((()=>{if(!a||!e||!t)return;const r=[...n];r.splice(s+1,0,[{id:e,params:{type:t}}]);const i=a.resolvePathFromState({panes:r});a.navigateUrl({path:i})}),[e,t,a,n,s])}function y(e,t,a){return{_key:e,value:{_type:"reference",_ref:t,_weak:!0,_strengthenOnPublish:{type:a}}}}function x(e){var a;const{index:r,language:u,languageField:d,schemaType:p,documentId:h,disabled:g,current:m,sourceId:x,sourceLanguageId:b,metadata:j,translation:v}=e,T=s.useClient(),k=i.useToast(),_=f(null==(a=null==v?void 0:v.value)?void 0:a._ref,p),C=o.useCallback((()=>_()),[_]),I=o.useCallback((async()=>{var e;const a=Boolean(null==j?void 0:j._id),n=T.transaction(),s=h.startsWith("drafts.")?[h,h.replace("drafts.","")]:[h,"drafts.".concat(h)],i=t(t({},await T.fetch("*[_id in $ids]|order(_updatedAt desc)[0]",{ids:s})),{},{_id:"drafts.".concat(c.uuid()),[d]:u.id});n.create(i);const l=null!=(e=null==j?void 0:j._id)?e:c.uuid(),o=y(u.id,i._id.replace("drafts.",""),p);if(a){const e="translations[".concat(r-1,"]"),t=T.patch(l).setIfMissing({translations:[]}).insert("before",e,[o]);n.patch(t)}else{const e=b?y(b,x,p):null;n.createIfNotExists({_id:l,_type:"translation.metadata",schemaTypes:[p],translations:[o,e].filter(Boolean)})}n.commit().then((()=>k.push({status:"success",title:"Created ".concat(u.title," translation"),description:a?"Updated Translations Metadata":"Created Translations Metadata"}))).catch((e=>(console.error(e),k.push({status:"error",title:"Error creating translation",description:e.message}))))}),[T,h,r,u,d,null==j?void 0:j._id,p,x,b,k]);return n.jsx(i.Button,{onClick:v?C:I,mode:m?"default":"bleed",disabled:g||m,children:n.jsxs(i.Flex,{gap:3,align:"center",children:[g?n.jsx(i.Spinner,{}):n.jsx(i.Text,{size:2,children:v?n.jsx(l.SplitVerticalIcon,{}):m?n.jsx(l.CheckmarkIcon,{}):n.jsx(l.AddIcon,{})}),n.jsx(i.Box,{flex:1,children:n.jsx(i.Text,{children:u.title})}),n.jsx(i.Badge,{tone:g||m?"default":"primary",children:u.id})]})})}function b(e){const{id:t}=e,a=f(t,"translation.metadata");return n.jsx(i.Button,{disabled:!t,mode:"ghost",text:"Manage Translations",icon:l.CogIcon,onClick:()=>a()})}function j(e){const{language:t,languageField:a,documentId:r,schemaType:o,source:c,disabled:u=!1}=e,d=s.useClient(),p=i.useToast(),h=g.default.useCallback((()=>{const e=c?c._id:"draft.".concat(r),n=d.transaction();c||n.createIfNotExists({_id:e,_type:o});const s=d.patch(e).set({[a]:t.id});n.patch(s),n.commit().then((()=>{p.push({title:"Set document language to ".concat(t.title),status:"success"})})).catch((e=>(console.error(e),p.push({title:"Failed to set document language to ".concat(t.title),status:"error"}))))}),[c,r,d,a,t,o,p]);return n.jsx(i.Button,{mode:"ghost",text:t.title,icon:l.ChevronRightIcon,onClick:()=>h(),disabled:u,justify:"flex-start"})}function v(e){const{supportedLanguages:t,schemaType:a,documentId:r,languageField:c}=e,[u,d]=o.useState(!1),h=o.useCallback((()=>d((e=>!e))),[]),[g,m]=o.useState(null),[f,y]=o.useState(null),v=o.useCallback((()=>d(!1)),[]);i.useClickOutside(v,[g,f]);const{data:T,loading:k,error:_}=function(e,t){const{data:a,loading:n,error:s}=p.useListeningQuery("*[_type == $translationSchema && $id in translations[].value._ref][0]",{params:{id:e,translationSchema:"translation.metadata"}});return{data:a,loading:n,error:s}}(r),{draft:C,published:I}=s.useEditState(r,a),S=C||I,O=null==S?void 0:S[c],P=t.some((e=>e.id===O)),F=n.jsx(i.Box,{overflow:"auto",children:_?n.jsx(i.Card,{tone:"critical",padding:2,children:n.jsxs(i.Text,{children:["Error: ",_]})}):n.jsxs(i.Stack,{padding:1,space:1,children:[t.length>0?n.jsxs(n.Fragment,{children:[t.map(((e,t)=>{var s;return!k&&O&&P?n.jsx(x,{index:t,language:e,languageField:c,schemaType:a,documentId:r,disabled:k,current:e.id===O,metadata:T,sourceId:r,sourceLanguageId:O,translation:null==T?void 0:T.translations.find((t=>t._key===e.id))},e.id):n.jsx(j,{languageField:c,source:S,documentId:r,schemaType:a,language:e,disabled:null!=(s=null==T?void 0:T.translations.filter((e=>{var t;return(null==(t=null==e?void 0:e.value)?void 0:t._ref)!==r})).some((t=>t._key===e.id)))&&s},e.id)})),k?null:n.jsxs(n.Fragment,{children:[O?null:n.jsx(i.Card,{tone:"caution",padding:3,children:n.jsxs(i.Text,{size:1,children:["Choose a language to ",n.jsx("br",{}),"apply to ",n.jsx("strong",{children:"this Document"})]})}),O&&!P?n.jsx(i.Card,{tone:"caution",padding:3,children:n.jsxs(i.Text,{size:1,children:["Change the current language value ",n.jsx("code",{children:O}),n.jsx("br",{}),"to one of the supported languages"]})}):null]})]}):null,n.jsx(b,{id:null==T?void 0:T._id})]})});return n.jsx(i.Popover,{constrainSize:!0,content:F,open:u,portal:!0,ref:y,children:n.jsx(i.Button,{text:"Translations",mode:"bleed",disabled:!S,tone:!S||!k&&O&&P?void 0:"caution",icon:l.TranslateIcon,onClick:h,ref:m,selected:u})})}function T(e){const{id:t,addId:a,removeId:r}=e,l=s.useEditState(t,""),o=s.useValidationStatus(t,""),c=s.useSchema(),u=g.default.useMemo((()=>o.validation.length>0&&o.validation.find((e=>"error"===e.level))),[o]);return g.default.useEffect((()=>{u?a(t):r(t)}),[a,t,r,u]),l.draft?n.jsx(i.Card,{border:!0,padding:2,tone:u?"critical":"positive",children:l.published?n.jsx(s.SanityPreview,{layout:"default",value:l.published,schemaType:c.get(l.published._type)}):n.jsx(i.Spinner,{})}):null}function k(e){const{translations:t}=e.value,a=s.useClient({apiVersion:"v2022-11-21"}),{projectId:r,dataset:l}=s.useWorkspace(),c=i.useToast(),[u,d]=g.default.useState([]),p=o.useCallback((e=>{d((t=>[...t,e]))}),[]),h=o.useCallback((e=>{d((t=>t.filter((t=>t!==e))))}),[]),m=o.useCallback((()=>{const e=t.map((e=>({documentId:e.value._ref})));a.request({uri:"/publish/".concat(r,"/").concat(l),method:"POST",body:e}).then((e=>{c.push({status:"success",title:"Success",description:"Bulk publish complete"})})).catch((e=>{console.error(e),c.push({status:"error",title:"Error",description:"Bulk publish failed"})}))}),[t,a,r,l,c]);return(null==t?void 0:t.length)>0?n.jsxs(i.Stack,{space:4,children:[n.jsxs(i.Stack,{space:3,children:[n.jsx(i.Text,{weight:"bold",size:1,children:"Bulk publishing"}),n.jsxs(i.Text,{children:["There"," ",1===t.length?"is 1 document":"are ".concat(t.length," documents"),"."]}),u.length>0?n.jsxs(i.Text,{weight:"medium",children:[1===u.length?"1 draft has":"".concat(u.length," drafts have")," ","validation issues that must addressed first."]}):n.jsx(i.Text,{children:"They are all valid."})]}),n.jsx(i.Stack,{space:2,children:t.map((e=>n.jsx(T,{id:e.value._ref,addId:p,removeId:h},e._key)))}),n.jsx(i.Button,{text:"Simultaneously Publish ".concat(1===t.length?"1 Document":"".concat(t.length," Documents")),onClick:m,disabled:Boolean(u.length)})]}):null}const _={supportedLanguages:[],schemaTypes:[],languageField:"language",bulkPublish:!1},C=s.definePlugin((e=>{const{supportedLanguages:a,schemaTypes:l,languageField:o,bulkPublish:c}=t(t({},_),e);return{name:"@sanity/document-internationalization",form:{components:{input:e=>c&&"root"===e.id&&"translation.metadata"===e.schemaType.name?n.jsxs(i.Stack,{space:5,children:[n.jsx(k,t({},e)),e.renderDefault(e)]}):e.renderDefault(e)}},document:{unstable_languageFilter:(e,t)=>{const{schemaType:s,documentId:r}=t;return l.includes(s)?[...e,()=>((e,t)=>n.jsx(v,{supportedLanguages:a,schemaType:e,documentId:null!=t?t:"",languageField:o}))(s,r)]:e},badges:(e,t)=>{let{schemaType:n}=t;return l.includes(n)?[e=>function(e,t,a){const n=(null==e?void 0:e.draft)||(null==e?void 0:e.published),s=null==n?void 0:n[a],r=t.find((e=>e.id===s));return r?{label:r.id,title:r.title,color:"primary"}:null}(e,a,o),...e]:e}},schema:{types:[m(l)],templates:(e,t)=>{let{schema:n}=t;return[...e,...l.map((e=>{var t,a;return{id:"".concat(e,"-parameterized"),title:"".concat(null!=(a=null==(t=null==n?void 0:n.get(e))?void 0:t.title)?a:e,": with Language"),schemaType:e,parameters:[{name:"languageId",title:"Language ID",type:"string"}],value:e=>{let{languageId:t}=e;return{[o]:t}}}})),...l.flatMap((e=>a.map((t=>({id:"".concat(e,"-").concat(t.id),title:"".concat(t.title," Lesson"),schemaType:e,value:{[o]:t.id}})))))]}},plugins:[r.internationalizedArray({languages:a,fieldTypes:[s.defineField({name:"reference",type:"reference",to:l.map((e=>({type:e}))),options:{collapsed:!1,filter:e=>{let{parent:t,document:a}=e;if(!t)return null;const n=(Array.isArray(t)?t:[t]).find((e=>e._key));return(null==n?void 0:n._key)?a.schemaTypes?{filter:"_type in $schemaTypes && ".concat(o," == $language"),params:{schemaTypes:a.schemaTypes,language:n._key}}:{filter:"".concat(o," == $language"),params:{language:n._key}}:null}}},{strict:!1})]})]}}));exports.documentInternationalization=C;
2
2
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/schema/translation/metadata.ts","../src/constants.ts","../src/hooks/useOpenInNewPane.tsx","../src/components/LanguageOption.tsx","../src/components/LanguageManage.tsx","../src/components/LanguagePatch.tsx","../src/components/MenuButton.tsx","../src/hooks/useLanguageMetadata.tsx","../src/components/BulkPublish/DocumentCheck.tsx","../src/components/BulkPublish/index.tsx","../src/plugin.tsx","../src/badges/index.tsx"],"sourcesContent":["import {defineType, defineField} from 'sanity'\nimport {TranslateIcon} from '@sanity/icons'\n\nimport {METADATA_SCHEMA_NAME} from '../../constants'\n\n// TODO: TS having a hard time determining the return type here. Likely a V3 type problem.\n// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\nexport default (schemaTypes: string[]) =>\n defineType({\n type: 'document',\n name: METADATA_SCHEMA_NAME,\n title: 'Translation metadata',\n icon: TranslateIcon,\n liveEdit: true,\n fields: [\n defineField({\n name: 'translations',\n type: 'internationalizedArrayReference',\n }),\n defineField({\n name: 'schemaTypes',\n description:\n 'Used to filter the reference fields above so all translations share the same types.',\n type: 'array',\n of: [{type: 'string'}],\n options: {list: schemaTypes},\n readOnly: ({value}) => Boolean(value),\n }),\n ],\n preview: {\n select: {\n translations: 'translations',\n documentSchemaTypes: 'schemaTypes',\n },\n prepare(selection) {\n const {translations, documentSchemaTypes} = selection\n const title =\n translations.length === 1 ? `1 Translation` : `${translations.length} Translations`\n const languageKeys = translations.length\n ? translations.map((t: {_key: string}) => t._key.toUpperCase()).join(', ')\n : ``\n const subtitle = [\n languageKeys ? `(${languageKeys})` : null,\n documentSchemaTypes?.length\n ? documentSchemaTypes.map((s: string) => s.toUpperCase()).join(`, `)\n : `No Schemas Defined`,\n ]\n .filter(Boolean)\n .join(` `)\n\n return {\n title,\n subtitle,\n }\n },\n },\n })\n","export const METADATA_SCHEMA_NAME = `translation.metadata`\n","import React from 'react'\nimport {usePaneRouter} from 'sanity/desk'\nimport {RouterContext} from 'sanity/router'\n\nexport function useOpenInNewPane(id?: string, type?: string) {\n const routerContext = React.useContext(RouterContext)\n const {routerPanesState, groupIndex} = usePaneRouter()\n\n const openInNewPane = React.useCallback(() => {\n if (!routerContext || !id || !type) {\n return\n }\n\n const panes = [...routerPanesState]\n panes.splice(groupIndex + 1, 0, [\n {\n id: id,\n params: {type},\n },\n ])\n\n const href = routerContext.resolvePathFromState({panes})\n routerContext.navigateUrl({path: href})\n }, [id, type, routerContext, routerPanesState, groupIndex])\n\n return openInNewPane\n}\n","import React, {useCallback} from 'react'\nimport {useClient} from 'sanity'\nimport {Button, Badge, Box, Flex, Text, useToast, Spinner} from '@sanity/ui'\nimport {uuid} from '@sanity/uuid'\nimport {SplitVerticalIcon, AddIcon, CheckmarkIcon} from '@sanity/icons'\n\nimport {Language, Metadata, TranslationReference} from '../types'\nimport {METADATA_SCHEMA_NAME} from '../constants'\nimport {useOpenInNewPane} from '../hooks/useOpenInNewPane'\n\ntype LanguageOptionProps = {\n language: Language\n languageField: string\n index: number\n schemaType: string\n documentId: string\n disabled: boolean\n current: boolean\n sourceId: string\n sourceLanguageId?: string\n metadata?: Metadata | null\n translation?: TranslationReference\n}\n\nfunction createReference(key: string, ref: string, type: string) {\n return {\n _key: key,\n value: {\n _type: 'reference',\n _ref: ref,\n _weak: true,\n _strengthenOnPublish: {\n type,\n },\n },\n }\n}\n\nexport default function LanguageOption(props: LanguageOptionProps) {\n const {\n index,\n language,\n languageField,\n schemaType,\n documentId,\n disabled,\n current,\n sourceId,\n sourceLanguageId,\n metadata,\n translation,\n } = props\n const client = useClient()\n const toast = useToast()\n\n const open = useOpenInNewPane(translation?.value?._ref, schemaType)\n const handleOpen = useCallback(() => open(), [open])\n\n const handleCreate = useCallback(async () => {\n const metadataExists = Boolean(metadata?._id)\n const transaction = client.transaction()\n\n // 1. Duplicate current document\n // 2. Update language\n // 3. Add to translation metadata\n const documentIds = documentId.startsWith(`drafts.`)\n ? [documentId, documentId.replace(`drafts.`, ``)]\n : [documentId, `drafts.${documentId}`]\n const latestDocument = await client.fetch(`*[_id in $ids]|order(_updatedAt desc)[0]`, {\n ids: documentIds,\n })\n const newTranslationDocument = {\n ...latestDocument,\n _id: `drafts.${uuid()}`,\n [languageField]: language.id,\n }\n\n transaction.create(newTranslationDocument)\n\n const metadataId = metadata?._id ?? uuid()\n const newTranslationReference = createReference(\n language.id,\n newTranslationDocument._id.replace(`drafts.`, ``),\n schemaType\n )\n\n // Create translation metadata document if it doesn't already exist\n if (metadataExists) {\n const path = `translations[${index - 1}]`\n const metadataPatch = client\n .patch(metadataId)\n .setIfMissing({translations: []})\n .insert(`before`, path, [newTranslationReference])\n\n transaction.patch(metadataPatch)\n } else {\n // Source language relies on a field named `language` on the document\n const sourceReference = sourceLanguageId\n ? createReference(sourceLanguageId, sourceId, schemaType)\n : null\n\n transaction.createIfNotExists({\n _id: metadataId,\n _type: METADATA_SCHEMA_NAME,\n schemaTypes: [schemaType],\n translations: [newTranslationReference, sourceReference].filter(Boolean),\n })\n }\n\n transaction\n .commit()\n .then(() => {\n // openDocumentInSidePane(metadataId, `translation.metadata`)\n return toast.push({\n status: 'success',\n title: `Created ${language.title} translation`,\n description: metadataExists\n ? `Updated Translations Metadata`\n : `Created Translations Metadata`,\n })\n })\n .catch((err) => {\n console.error(err)\n\n return toast.push({\n status: 'error',\n title: `Error creating translation`,\n description: err.message,\n })\n })\n }, [\n client,\n documentId,\n index,\n language,\n languageField,\n metadata?._id,\n schemaType,\n sourceId,\n sourceLanguageId,\n toast,\n ])\n\n return (\n <Button\n onClick={translation ? handleOpen : handleCreate}\n mode={current ? `default` : `bleed`}\n disabled={disabled || current}\n >\n <Flex gap={3} align=\"center\">\n {disabled ? (\n <Spinner />\n ) : (\n <Text size={2}>\n {/* eslint-disable-next-line no-nested-ternary */}\n {translation ? <SplitVerticalIcon /> : current ? <CheckmarkIcon /> : <AddIcon />}\n </Text>\n )}\n <Box flex={1}>\n <Text>{language.title}</Text>\n </Box>\n <Badge tone={disabled || current ? `default` : `primary`}>{language.id}</Badge>\n </Flex>\n </Button>\n )\n}\n","import React from 'react'\nimport {CogIcon} from '@sanity/icons'\nimport {Button} from '@sanity/ui'\n\nimport {useOpenInNewPane} from '../hooks/useOpenInNewPane'\nimport {METADATA_SCHEMA_NAME} from '../constants'\n\ntype LanguageManageProps = {\n id?: string\n}\n\nexport default function LanguageManage(props: LanguageManageProps) {\n const {id} = props\n const open = useOpenInNewPane(id, METADATA_SCHEMA_NAME)\n\n return (\n <Button\n disabled={!id}\n mode=\"ghost\"\n text=\"Manage Translations\"\n icon={CogIcon}\n onClick={() => open()}\n />\n )\n}\n","import React from 'react'\nimport {ChevronRightIcon} from '@sanity/icons'\nimport {Button, useToast} from '@sanity/ui'\nimport {SanityDocument, useClient} from 'sanity'\n\nimport {Language} from '../types'\n\ntype LanguagePatchProps = {\n language: Language\n languageField: string\n documentId: string\n schemaType: string\n source: SanityDocument | null\n disabled: boolean\n}\n\nexport default function LanguagePatch(props: LanguagePatchProps) {\n const {language, languageField, documentId, schemaType, source, disabled = false} = props\n const client = useClient()\n const toast = useToast()\n\n const handleClick = React.useCallback(() => {\n const currentId = source ? source._id : `draft.${documentId}`\n const transaction = client.transaction()\n\n if (!source) {\n transaction.createIfNotExists({\n _id: currentId,\n _type: schemaType,\n })\n }\n\n const patch = client.patch(currentId).set({[languageField]: language.id})\n transaction.patch(patch)\n\n transaction\n .commit()\n .then(() => {\n toast.push({\n title: `Set document language to ${language.title}`,\n status: `success`,\n })\n })\n .catch((err) => {\n console.error(err)\n\n return toast.push({\n title: `Failed to set document language to ${language.title}`,\n status: `error`,\n })\n })\n }, [source, documentId, client, languageField, language, schemaType, toast])\n\n return (\n <Button\n mode=\"ghost\"\n text={language.title}\n icon={ChevronRightIcon}\n onClick={() => handleClick()}\n disabled={disabled}\n justify=\"flex-start\"\n />\n )\n}\n","import React, {useCallback, useState} from 'react'\nimport {Text, Card, useClickOutside, Stack, Popover, Button, Box} from '@sanity/ui'\nimport {TranslateIcon} from '@sanity/icons'\nimport {useEditState} from 'sanity'\n\nimport {Language} from '../types'\nimport LanguageOption from './LanguageOption'\nimport {useTranslationMetadata} from '../hooks/useLanguageMetadata'\nimport LanguageManage from './LanguageManage'\nimport LanguagePatch from './LanguagePatch'\n\ntype MenuButtonProps = {\n supportedLanguages: Language[]\n schemaType: string\n documentId: string\n languageField: string\n}\n\nexport default function MenuButton(props: MenuButtonProps) {\n const {supportedLanguages, schemaType, documentId, languageField} = props\n\n const [open, setOpen] = useState(false)\n const handleClick = useCallback(() => setOpen((o) => !o), [])\n const [button, setButton] = useState<HTMLElement | null>(null)\n const [popover, setPopover] = useState<HTMLElement | null>(null)\n const handleClickOutside = useCallback(() => setOpen(false), [])\n useClickOutside(handleClickOutside, [button, popover])\n const {data: metadata, loading, error} = useTranslationMetadata(documentId, schemaType)\n const {draft, published} = useEditState(documentId, schemaType)\n const source = draft || published\n\n const sourceLanguageId = source?.[languageField] as string | undefined\n const sourceLanguageIsValid = supportedLanguages.some((l) => l.id === sourceLanguageId)\n\n const content = (\n <Box overflow=\"auto\">\n {error ? (\n <Card tone=\"critical\" padding={2}>\n <Text>Error: {error}</Text>\n </Card>\n ) : (\n <Stack padding={1} space={1}>\n {supportedLanguages.length > 0 ? (\n <>\n {supportedLanguages.map((language, langIndex) =>\n !loading && sourceLanguageId && sourceLanguageIsValid ? (\n // Button to duplicate this document to a new translation\n // And either create or update the metadata document\n <LanguageOption\n key={language.id}\n index={langIndex}\n language={language}\n languageField={languageField}\n schemaType={schemaType}\n documentId={documentId}\n disabled={loading}\n current={language.id === sourceLanguageId}\n metadata={metadata}\n sourceId={documentId}\n sourceLanguageId={sourceLanguageId}\n translation={metadata?.translations.find((t) => t._key === language.id)}\n />\n ) : (\n // Button to set a language field on *this* document\n <LanguagePatch\n key={language.id}\n languageField={languageField}\n source={source}\n documentId={documentId}\n schemaType={schemaType}\n language={language}\n // Only allow language patch change to:\n // - Keys not in metadata\n // - The key of this document in the metadata\n disabled={\n metadata?.translations\n .filter((t) => t?.value?._ref !== documentId)\n .some((t) => t._key === language.id) ?? false\n }\n />\n )\n )}\n {/* Once metadata is loaded, there may be issues */}\n {loading ? null : (\n <>\n {/* Current document has no language field */}\n {sourceLanguageId ? null : (\n <Card tone=\"caution\" padding={3}>\n <Text size={1}>\n Choose a language to <br />\n apply to <strong>this Document</strong>\n </Text>\n </Card>\n )}\n {/* Current document has an invalid language field */}\n {sourceLanguageId && !sourceLanguageIsValid ? (\n <Card tone=\"caution\" padding={3}>\n <Text size={1}>\n Change the current language value <code>{sourceLanguageId}</code>\n <br />\n to one of the supported languages\n </Text>\n </Card>\n ) : null}\n </>\n )}\n </>\n ) : null}\n <LanguageManage id={metadata?._id} />\n </Stack>\n )}\n </Box>\n )\n\n return (\n <Popover constrainSize content={content} open={open} portal ref={setPopover}>\n <Button\n text=\"Translations\"\n mode=\"bleed\"\n disabled={!source}\n tone={\n !source || (!loading && sourceLanguageId && sourceLanguageIsValid) ? undefined : `caution`\n }\n icon={TranslateIcon}\n onClick={handleClick}\n ref={setButton}\n selected={open}\n />\n </Popover>\n )\n}\n","import React from 'react'\nimport {useListeningQuery} from 'sanity-plugin-utils'\nimport {METADATA_SCHEMA_NAME} from '../constants'\n\nimport {Metadata} from '../types'\n\nexport function useTranslationMetadata(\n id: string,\n schemaType: string\n): {\n data: Metadata | null\n loading: boolean\n error: boolean\n} {\n const query = `*[_type == $translationSchema && $id in translations[].value._ref][0]`\n const {data, loading, error} = useListeningQuery<Metadata>(query, {\n params: {id, translationSchema: METADATA_SCHEMA_NAME},\n })\n\n return {data, loading, error}\n}\n","import React from 'react'\nimport {Card, Spinner} from '@sanity/ui'\nimport {\n useEditState,\n useValidationStatus,\n SanityPreview as Preview,\n SchemaType,\n useSchema,\n} from 'sanity'\n\ntype DocumentCheckProps = {\n id: string\n addId: (id: string) => void\n removeId: (id: string) => void\n}\n\n// Check if the document has a draft\n// Check if that draft is valid\n// Report back to parent that it can be added to bulk publish\nexport default function DocumentCheck(props: DocumentCheckProps) {\n const {id, addId, removeId} = props\n const editState = useEditState(id, ``)\n const validationStatus = useValidationStatus(id, ``)\n const schema = useSchema()\n\n const validationHasErrors = React.useMemo(() => {\n return (\n validationStatus.validation.length > 0 &&\n validationStatus.validation.find((item) => item.level === 'error')\n )\n }, [validationStatus])\n\n React.useEffect(() => {\n if (validationHasErrors) {\n addId(id)\n } else {\n removeId(id)\n }\n }, [addId, id, removeId, validationHasErrors])\n\n // We only care about drafts\n if (!editState.draft) {\n return null\n }\n\n return (\n <Card border padding={2} tone={validationHasErrors ? `critical` : `positive`}>\n {editState.published ? (\n <Preview\n layout=\"default\"\n value={editState.published}\n schemaType={schema.get(editState.published._type) as SchemaType}\n />\n ) : (\n <Spinner />\n )}\n </Card>\n )\n}\n","import React, {useCallback} from 'react'\nimport {Box, Text, Stack, Button, useToast} from '@sanity/ui'\nimport {\n InputProps,\n Reference,\n SanityDocument,\n KeyedObject,\n TypedObject,\n useClient,\n useWorkspace,\n} from 'sanity'\nimport DocumentCheck from './DocumentCheck'\n\nexport type TranslationReference = KeyedObject & TypedObject & {value: Reference}\n\nexport type TranslationMetadataDocument = SanityDocument & {\n translations: TranslationReference[]\n schemaTypes: string[]\n}\n\nexport default function BulkPublish(props: InputProps) {\n const {translations} = props.value as TranslationMetadataDocument\n const client = useClient({apiVersion: `v2022-11-21`})\n const {projectId, dataset} = useWorkspace()\n const toast = useToast()\n const [invalidIds, setInvalidIds] = React.useState<string[]>([])\n\n const addId = useCallback((id: string) => {\n setInvalidIds((ids) => [...ids, id])\n }, [])\n\n const removeId = useCallback((id: string) => {\n setInvalidIds((ids) => ids.filter((i) => i !== id))\n }, [])\n\n const handleBulkPublish = useCallback(() => {\n const body = translations.map((translation) => ({documentId: translation.value._ref}))\n client\n .request({\n uri: `/publish/${projectId}/${dataset}`,\n method: 'POST',\n body,\n })\n .then((res) => {\n toast.push({\n status: 'success',\n title: 'Success',\n description: 'Bulk publish complete',\n })\n })\n .catch((err) => {\n console.error(err)\n toast.push({\n status: 'error',\n title: 'Error',\n description: 'Bulk publish failed',\n })\n })\n }, [translations, client, projectId, dataset, toast])\n\n // TODO: Hide all this if none of the documents have drafts\n return translations?.length > 0 ? (\n <Stack space={4}>\n <Stack space={3}>\n <Text weight=\"bold\" size={1}>\n Bulk publishing\n </Text>\n <Text>\n There{' '}\n {translations.length === 1 ? `is 1 document` : `are ${translations.length} documents`}.\n </Text>\n {invalidIds.length > 0 ? (\n <Text weight=\"medium\">\n {invalidIds.length === 1 ? `1 draft has` : `${invalidIds.length} drafts have`}{' '}\n validation issues that must addressed first.\n </Text>\n ) : (\n <Text>They are all valid.</Text>\n )}\n </Stack>\n <Stack space={2}>\n {translations.map((translation) => (\n <DocumentCheck\n key={translation._key}\n id={translation.value._ref}\n addId={addId}\n removeId={removeId}\n />\n ))}\n </Stack>\n <Button\n text={`Simultaneously Publish ${\n translations.length === 1 ? `1 Document` : `${translations.length} Documents`\n }`}\n onClick={handleBulkPublish}\n disabled={Boolean(invalidIds.length)}\n />\n </Stack>\n ) : null\n}\n","import React from 'react'\nimport {definePlugin, defineField} from 'sanity'\nimport {internationalizedArray} from 'sanity-plugin-internationalized-array'\nimport {Stack} from '@sanity/ui'\n\nimport metadata from './schema/translation/metadata'\nimport MenuButton from './components/MenuButton'\nimport {PluginConfig} from './types'\nimport {LanguageBadge} from './badges'\nimport {METADATA_SCHEMA_NAME} from './constants'\nimport BulkPublish from './components/BulkPublish'\n\nconst DEFAULT_CONFIG = {\n supportedLanguages: [],\n schemaTypes: [],\n languageField: `language`,\n bulkPublish: false,\n}\n\nexport const documentInternationalization = definePlugin<PluginConfig>((config) => {\n const {supportedLanguages, schemaTypes, languageField, bulkPublish} = {\n ...DEFAULT_CONFIG,\n ...config,\n }\n\n const renderLanguageFilter = (schemaType: string, documentId?: string) => {\n return (\n <MenuButton\n supportedLanguages={supportedLanguages}\n schemaType={schemaType}\n documentId={documentId ?? ``}\n languageField={languageField}\n />\n )\n }\n\n return {\n name: '@sanity/document-internationalization',\n\n // Adds:\n // - A bulk-publishing UI component to the form\n // - Will only work for projects on a compatible plan\n form: {\n components: {\n input: (props) => {\n if (\n bulkPublish &&\n props.id === 'root' &&\n props.schemaType.name === METADATA_SCHEMA_NAME\n ) {\n return (\n <Stack space={5}>\n <BulkPublish {...props} />\n {props.renderDefault(props)}\n </Stack>\n )\n }\n\n return props.renderDefault(props)\n },\n },\n },\n\n // Adds:\n // - The `Translations` dropdown to the editing form\n // - `Badges` to documents with a language value\n document: {\n unstable_languageFilter: (prev, ctx) => {\n const {schemaType, documentId} = ctx\n\n return schemaTypes.includes(schemaType)\n ? [...prev, () => renderLanguageFilter(schemaType, documentId)]\n : prev\n },\n badges: (prev, {schemaType}) => {\n if (!schemaTypes.includes(schemaType)) {\n return prev\n }\n\n return [(props) => LanguageBadge(props, supportedLanguages, languageField), ...prev]\n },\n },\n\n // Adds:\n // - The `Translations metadata` document type to the schema\n schema: {\n // Create the metadata document type\n types: [metadata(schemaTypes)],\n\n // For every schema type this plugin is enabled on\n // Create an initial value template to set the language\n templates: (prev, {schema}) => {\n const parameterizedTemplates = schemaTypes.map((schemaType) => ({\n id: `${schemaType}-parameterized`,\n title: `${schema?.get(schemaType)?.title ?? schemaType}: with Language`,\n schemaType,\n parameters: [{name: `languageId`, title: `Language ID`, type: `string`}],\n value: ({languageId}: {languageId: string}) => ({\n [languageField]: languageId,\n }),\n }))\n\n const staticTemplates = schemaTypes.flatMap((schemaType) => {\n return supportedLanguages.map((language) => ({\n id: `${schemaType}-${language.id}`,\n title: `${language.title} Lesson`,\n schemaType,\n value: {\n [languageField]: language.id,\n },\n }))\n })\n\n return [...prev, ...parameterizedTemplates, ...staticTemplates]\n },\n },\n\n // Uses:\n // - `sanity-plugin-internationalized-array` to maintain the translations array\n plugins: [\n // Translation metadata stores its references using this plugin\n // It cuts down on attribute usage and gives UI conveniences to add new translations\n internationalizedArray({\n languages: supportedLanguages,\n fieldTypes: [\n // TODO: The plugin should allow this kind of input\n // @ts-ignore\n defineField(\n {\n name: 'reference',\n type: 'reference',\n to: schemaTypes.map((type) => ({type: type})),\n // TODO: Add a validation rule to *ensure* the document's language matches the array key\n // Reference filters don't actually enforce validation!\n // validation: (Rule) => Rule.custom(),\n options: {\n collapsed: false,\n // TODO: Update type once it knows the values of this filter\n // @ts-ignore\n filter: ({parent, document}) => {\n if (!parent) return null\n\n // I'm not sure in what instance there's an array of parents\n // But the Type suggests it's possible\n const parentArray = Array.isArray(parent) ? parent : [parent]\n const language = !parentArray.find((p) => p._key)?._key\n\n if (!language) return null\n\n if (document.schemaTypes) {\n return {\n filter: `_type in $schemaTypes && ${languageField} == $language`,\n params: {schemaTypes: document.schemaTypes, language},\n }\n }\n\n return {\n filter: `${languageField} == $language`,\n params: {language},\n }\n },\n },\n },\n {strict: false}\n ),\n ],\n }),\n ],\n }\n})\n","import {DocumentBadgeDescription, DocumentBadgeProps} from 'sanity'\n\nimport {Language} from '../types'\n\nexport function LanguageBadge(\n props: DocumentBadgeProps,\n supportedLanguages: Language[],\n languageField: string\n): DocumentBadgeDescription | null {\n const source = props?.draft || props?.published\n const languageId = source?.[languageField]\n const language = supportedLanguages.find((l) => l.id === languageId)\n\n if (!language) {\n return null\n }\n\n return {\n label: language.id,\n title: language.title,\n color: `primary`,\n }\n}\n"],"names":["metadata","schemaTypes","defineType","type","name","title","icon","TranslateIcon","liveEdit","fields","defineField","description","of","options","list","readOnly","_ref","value","Boolean","preview","select","translations","documentSchemaTypes","prepare","selection","length","languageKeys","map","t","_key","toUpperCase","join","subtitle","s","filter","useOpenInNewPane","id","routerContext","React","useContext","RouterContext","routerPanesState","groupIndex","usePaneRouter","useCallback","panes","splice","params","href","resolvePathFromState","navigateUrl","path","createReference","key","ref","_type","_weak","_strengthenOnPublish","LanguageOption","props","_a","index","language","languageField","schemaType","documentId","disabled","current","sourceId","sourceLanguageId","translation","client","useClient","toast","useToast","open","handleOpen","handleCreate","async","metadataExists","_id","transaction","documentIds","startsWith","replace","concat","newTranslationDocument","fetch","ids","uuid","create","metadataId","newTranslationReference","metadataPatch","patch","setIfMissing","insert","sourceReference","createIfNotExists","commit","then","push","status","catch","err","console","error","message","jsx","Button","onClick","mode","children","jsxs","Flex","gap","align","Spinner","Text","size","SplitVerticalIcon","CheckmarkIcon","AddIcon","Box","flex","Badge","tone","LanguageManage","text","CogIcon","LanguagePatch","source","handleClick","currentId","set","ChevronRightIcon","justify","MenuButton","supportedLanguages","setOpen","useState","o","button","setButton","popover","setPopover","handleClickOutside","useClickOutside","data","loading","useListeningQuery","translationSchema","useTranslationMetadata","draft","published","useEditState","sourceLanguageIsValid","some","l","content","overflow","Card","padding","Stack","space","Fragment","langIndex","find","Popover","constrainSize","portal","selected","DocumentCheck","addId","removeId","editState","validationStatus","useValidationStatus","schema","useSchema","validationHasErrors","useMemo","validation","item","level","useEffect","border","Preview","layout","get","BulkPublish","apiVersion","projectId","dataset","useWorkspace","invalidIds","setInvalidIds","i","handleBulkPublish","body","request","uri","method","res","weight","DEFAULT_CONFIG","bulkPublish","documentInternationalization","definePlugin","config","form","components","input","renderDefault","document","unstable_languageFilter","prev","ctx","includes","renderLanguageFilter","badges","_ref2","languageId","label","color","LanguageBadge","types","templates","_ref3","_b","parameters","_ref4","flatMap","plugins","internationalizedArray","languages","fieldTypes","to","collapsed","_ref5","parent","Array","isArray","p","strict"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/schema/translation/metadata.ts","../src/constants.ts","../src/hooks/useOpenInNewPane.tsx","../src/components/LanguageOption.tsx","../src/components/LanguageManage.tsx","../src/components/LanguagePatch.tsx","../src/components/MenuButton.tsx","../src/hooks/useLanguageMetadata.tsx","../src/components/BulkPublish/DocumentCheck.tsx","../src/components/BulkPublish/index.tsx","../src/plugin.tsx","../src/badges/index.tsx"],"sourcesContent":["import {defineType, defineField} from 'sanity'\nimport {TranslateIcon} from '@sanity/icons'\n\nimport {METADATA_SCHEMA_NAME} from '../../constants'\n\n// TODO: TS having a hard time determining the return type here. Likely a V3 type problem.\n// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types\nexport default (schemaTypes: string[]) =>\n defineType({\n type: 'document',\n name: METADATA_SCHEMA_NAME,\n title: 'Translation metadata',\n icon: TranslateIcon,\n liveEdit: true,\n fields: [\n defineField({\n name: 'translations',\n type: 'internationalizedArrayReference',\n }),\n defineField({\n name: 'schemaTypes',\n description:\n 'Used to filter the reference fields above so all translations share the same types.',\n type: 'array',\n of: [{type: 'string'}],\n options: {list: schemaTypes},\n readOnly: ({value}) => Boolean(value),\n }),\n ],\n preview: {\n select: {\n translations: 'translations',\n documentSchemaTypes: 'schemaTypes',\n },\n prepare(selection) {\n const {translations, documentSchemaTypes} = selection\n const title =\n translations.length === 1 ? `1 Translation` : `${translations.length} Translations`\n const languageKeys = translations.length\n ? translations.map((t: {_key: string}) => t._key.toUpperCase()).join(', ')\n : ``\n const subtitle = [\n languageKeys ? `(${languageKeys})` : null,\n documentSchemaTypes?.length\n ? documentSchemaTypes.map((s: string) => s.toUpperCase()).join(`, `)\n : `No Schemas Defined`,\n ]\n .filter(Boolean)\n .join(` `)\n\n return {\n title,\n subtitle,\n }\n },\n },\n })\n","export const METADATA_SCHEMA_NAME = `translation.metadata`\n","import React from 'react'\nimport {usePaneRouter} from 'sanity/desk'\nimport {RouterContext} from 'sanity/router'\n\nexport function useOpenInNewPane(id?: string, type?: string) {\n const routerContext = React.useContext(RouterContext)\n const {routerPanesState, groupIndex} = usePaneRouter()\n\n const openInNewPane = React.useCallback(() => {\n if (!routerContext || !id || !type) {\n return\n }\n\n const panes = [...routerPanesState]\n panes.splice(groupIndex + 1, 0, [\n {\n id: id,\n params: {type},\n },\n ])\n\n const href = routerContext.resolvePathFromState({panes})\n routerContext.navigateUrl({path: href})\n }, [id, type, routerContext, routerPanesState, groupIndex])\n\n return openInNewPane\n}\n","import React, {useCallback} from 'react'\nimport {useClient} from 'sanity'\nimport {Button, Badge, Box, Flex, Text, useToast, Spinner} from '@sanity/ui'\nimport {uuid} from '@sanity/uuid'\nimport {SplitVerticalIcon, AddIcon, CheckmarkIcon} from '@sanity/icons'\n\nimport {Language, Metadata, TranslationReference} from '../types'\nimport {METADATA_SCHEMA_NAME} from '../constants'\nimport {useOpenInNewPane} from '../hooks/useOpenInNewPane'\n\ntype LanguageOptionProps = {\n language: Language\n languageField: string\n index: number\n schemaType: string\n documentId: string\n disabled: boolean\n current: boolean\n sourceId: string\n sourceLanguageId?: string\n metadata?: Metadata | null\n translation?: TranslationReference\n}\n\nfunction createReference(key: string, ref: string, type: string) {\n return {\n _key: key,\n value: {\n _type: 'reference',\n _ref: ref,\n _weak: true,\n _strengthenOnPublish: {\n type,\n },\n },\n }\n}\n\nexport default function LanguageOption(props: LanguageOptionProps) {\n const {\n index,\n language,\n languageField,\n schemaType,\n documentId,\n disabled,\n current,\n sourceId,\n sourceLanguageId,\n metadata,\n translation,\n } = props\n const client = useClient()\n const toast = useToast()\n\n const open = useOpenInNewPane(translation?.value?._ref, schemaType)\n const handleOpen = useCallback(() => open(), [open])\n\n const handleCreate = useCallback(async () => {\n const metadataExists = Boolean(metadata?._id)\n const transaction = client.transaction()\n\n // 1. Duplicate current document\n // 2. Update language\n // 3. Add to translation metadata\n const documentIds = documentId.startsWith(`drafts.`)\n ? [documentId, documentId.replace(`drafts.`, ``)]\n : [documentId, `drafts.${documentId}`]\n const latestDocument = await client.fetch(`*[_id in $ids]|order(_updatedAt desc)[0]`, {\n ids: documentIds,\n })\n const newTranslationDocument = {\n ...latestDocument,\n _id: `drafts.${uuid()}`,\n [languageField]: language.id,\n }\n\n transaction.create(newTranslationDocument)\n\n const metadataId = metadata?._id ?? uuid()\n const newTranslationReference = createReference(\n language.id,\n newTranslationDocument._id.replace(`drafts.`, ``),\n schemaType\n )\n\n // Create translation metadata document if it doesn't already exist\n if (metadataExists) {\n const path = `translations[${index - 1}]`\n const metadataPatch = client\n .patch(metadataId)\n .setIfMissing({translations: []})\n .insert(`before`, path, [newTranslationReference])\n\n transaction.patch(metadataPatch)\n } else {\n // Source language relies on a field named `language` on the document\n const sourceReference = sourceLanguageId\n ? createReference(sourceLanguageId, sourceId, schemaType)\n : null\n\n transaction.createIfNotExists({\n _id: metadataId,\n _type: METADATA_SCHEMA_NAME,\n schemaTypes: [schemaType],\n translations: [newTranslationReference, sourceReference].filter(Boolean),\n })\n }\n\n transaction\n .commit()\n .then(() => {\n // openDocumentInSidePane(metadataId, `translation.metadata`)\n return toast.push({\n status: 'success',\n title: `Created ${language.title} translation`,\n description: metadataExists\n ? `Updated Translations Metadata`\n : `Created Translations Metadata`,\n })\n })\n .catch((err) => {\n console.error(err)\n\n return toast.push({\n status: 'error',\n title: `Error creating translation`,\n description: err.message,\n })\n })\n }, [\n client,\n documentId,\n index,\n language,\n languageField,\n metadata?._id,\n schemaType,\n sourceId,\n sourceLanguageId,\n toast,\n ])\n\n return (\n <Button\n onClick={translation ? handleOpen : handleCreate}\n mode={current ? `default` : `bleed`}\n disabled={disabled || current}\n >\n <Flex gap={3} align=\"center\">\n {disabled ? (\n <Spinner />\n ) : (\n <Text size={2}>\n {/* eslint-disable-next-line no-nested-ternary */}\n {translation ? <SplitVerticalIcon /> : current ? <CheckmarkIcon /> : <AddIcon />}\n </Text>\n )}\n <Box flex={1}>\n <Text>{language.title}</Text>\n </Box>\n <Badge tone={disabled || current ? `default` : `primary`}>{language.id}</Badge>\n </Flex>\n </Button>\n )\n}\n","import React from 'react'\nimport {CogIcon} from '@sanity/icons'\nimport {Button} from '@sanity/ui'\n\nimport {useOpenInNewPane} from '../hooks/useOpenInNewPane'\nimport {METADATA_SCHEMA_NAME} from '../constants'\n\ntype LanguageManageProps = {\n id?: string\n}\n\nexport default function LanguageManage(props: LanguageManageProps) {\n const {id} = props\n const open = useOpenInNewPane(id, METADATA_SCHEMA_NAME)\n\n return (\n <Button\n disabled={!id}\n mode=\"ghost\"\n text=\"Manage Translations\"\n icon={CogIcon}\n onClick={() => open()}\n />\n )\n}\n","import React from 'react'\nimport {ChevronRightIcon} from '@sanity/icons'\nimport {Button, useToast} from '@sanity/ui'\nimport {SanityDocument, useClient} from 'sanity'\n\nimport {Language} from '../types'\n\ntype LanguagePatchProps = {\n language: Language\n languageField: string\n documentId: string\n schemaType: string\n source: SanityDocument | null\n disabled: boolean\n}\n\nexport default function LanguagePatch(props: LanguagePatchProps) {\n const {language, languageField, documentId, schemaType, source, disabled = false} = props\n const client = useClient()\n const toast = useToast()\n\n const handleClick = React.useCallback(() => {\n const currentId = source ? source._id : `draft.${documentId}`\n const transaction = client.transaction()\n\n if (!source) {\n transaction.createIfNotExists({\n _id: currentId,\n _type: schemaType,\n })\n }\n\n const patch = client.patch(currentId).set({[languageField]: language.id})\n transaction.patch(patch)\n\n transaction\n .commit()\n .then(() => {\n toast.push({\n title: `Set document language to ${language.title}`,\n status: `success`,\n })\n })\n .catch((err) => {\n console.error(err)\n\n return toast.push({\n title: `Failed to set document language to ${language.title}`,\n status: `error`,\n })\n })\n }, [source, documentId, client, languageField, language, schemaType, toast])\n\n return (\n <Button\n mode=\"ghost\"\n text={language.title}\n icon={ChevronRightIcon}\n onClick={() => handleClick()}\n disabled={disabled}\n justify=\"flex-start\"\n />\n )\n}\n","import React, {useCallback, useState} from 'react'\nimport {Text, Card, useClickOutside, Stack, Popover, Button, Box} from '@sanity/ui'\nimport {TranslateIcon} from '@sanity/icons'\nimport {useEditState} from 'sanity'\n\nimport {Language} from '../types'\nimport LanguageOption from './LanguageOption'\nimport {useTranslationMetadata} from '../hooks/useLanguageMetadata'\nimport LanguageManage from './LanguageManage'\nimport LanguagePatch from './LanguagePatch'\n\ntype MenuButtonProps = {\n supportedLanguages: Language[]\n schemaType: string\n documentId: string\n languageField: string\n}\n\nexport default function MenuButton(props: MenuButtonProps) {\n const {supportedLanguages, schemaType, documentId, languageField} = props\n\n const [open, setOpen] = useState(false)\n const handleClick = useCallback(() => setOpen((o) => !o), [])\n const [button, setButton] = useState<HTMLElement | null>(null)\n const [popover, setPopover] = useState<HTMLElement | null>(null)\n const handleClickOutside = useCallback(() => setOpen(false), [])\n useClickOutside(handleClickOutside, [button, popover])\n const {data: metadata, loading, error} = useTranslationMetadata(documentId, schemaType)\n const {draft, published} = useEditState(documentId, schemaType)\n const source = draft || published\n\n const sourceLanguageId = source?.[languageField] as string | undefined\n const sourceLanguageIsValid = supportedLanguages.some((l) => l.id === sourceLanguageId)\n\n const content = (\n <Box overflow=\"auto\">\n {error ? (\n <Card tone=\"critical\" padding={2}>\n <Text>Error: {error}</Text>\n </Card>\n ) : (\n <Stack padding={1} space={1}>\n {supportedLanguages.length > 0 ? (\n <>\n {supportedLanguages.map((language, langIndex) =>\n !loading && sourceLanguageId && sourceLanguageIsValid ? (\n // Button to duplicate this document to a new translation\n // And either create or update the metadata document\n <LanguageOption\n key={language.id}\n index={langIndex}\n language={language}\n languageField={languageField}\n schemaType={schemaType}\n documentId={documentId}\n disabled={loading}\n current={language.id === sourceLanguageId}\n metadata={metadata}\n sourceId={documentId}\n sourceLanguageId={sourceLanguageId}\n translation={metadata?.translations.find((t) => t._key === language.id)}\n />\n ) : (\n // Button to set a language field on *this* document\n <LanguagePatch\n key={language.id}\n languageField={languageField}\n source={source}\n documentId={documentId}\n schemaType={schemaType}\n language={language}\n // Only allow language patch change to:\n // - Keys not in metadata\n // - The key of this document in the metadata\n disabled={\n metadata?.translations\n .filter((t) => t?.value?._ref !== documentId)\n .some((t) => t._key === language.id) ?? false\n }\n />\n )\n )}\n {/* Once metadata is loaded, there may be issues */}\n {loading ? null : (\n <>\n {/* Current document has no language field */}\n {sourceLanguageId ? null : (\n <Card tone=\"caution\" padding={3}>\n <Text size={1}>\n Choose a language to <br />\n apply to <strong>this Document</strong>\n </Text>\n </Card>\n )}\n {/* Current document has an invalid language field */}\n {sourceLanguageId && !sourceLanguageIsValid ? (\n <Card tone=\"caution\" padding={3}>\n <Text size={1}>\n Change the current language value <code>{sourceLanguageId}</code>\n <br />\n to one of the supported languages\n </Text>\n </Card>\n ) : null}\n </>\n )}\n </>\n ) : null}\n <LanguageManage id={metadata?._id} />\n </Stack>\n )}\n </Box>\n )\n\n return (\n <Popover constrainSize content={content} open={open} portal ref={setPopover}>\n <Button\n text=\"Translations\"\n mode=\"bleed\"\n disabled={!source}\n tone={\n !source || (!loading && sourceLanguageId && sourceLanguageIsValid) ? undefined : `caution`\n }\n icon={TranslateIcon}\n onClick={handleClick}\n ref={setButton}\n selected={open}\n />\n </Popover>\n )\n}\n","import React from 'react'\nimport {useListeningQuery} from 'sanity-plugin-utils'\nimport {METADATA_SCHEMA_NAME} from '../constants'\n\nimport {Metadata} from '../types'\n\nexport function useTranslationMetadata(\n id: string,\n schemaType: string\n): {\n data: Metadata | null\n loading: boolean\n error: boolean\n} {\n const query = `*[_type == $translationSchema && $id in translations[].value._ref][0]`\n const {data, loading, error} = useListeningQuery<Metadata>(query, {\n params: {id, translationSchema: METADATA_SCHEMA_NAME},\n })\n\n return {data, loading, error}\n}\n","import React from 'react'\nimport {Card, Spinner} from '@sanity/ui'\nimport {\n useEditState,\n useValidationStatus,\n SanityPreview as Preview,\n SchemaType,\n useSchema,\n} from 'sanity'\n\ntype DocumentCheckProps = {\n id: string\n addId: (id: string) => void\n removeId: (id: string) => void\n}\n\n// Check if the document has a draft\n// Check if that draft is valid\n// Report back to parent that it can be added to bulk publish\nexport default function DocumentCheck(props: DocumentCheckProps) {\n const {id, addId, removeId} = props\n const editState = useEditState(id, ``)\n const validationStatus = useValidationStatus(id, ``)\n const schema = useSchema()\n\n const validationHasErrors = React.useMemo(() => {\n return (\n validationStatus.validation.length > 0 &&\n validationStatus.validation.find((item) => item.level === 'error')\n )\n }, [validationStatus])\n\n React.useEffect(() => {\n if (validationHasErrors) {\n addId(id)\n } else {\n removeId(id)\n }\n }, [addId, id, removeId, validationHasErrors])\n\n // We only care about drafts\n if (!editState.draft) {\n return null\n }\n\n return (\n <Card border padding={2} tone={validationHasErrors ? `critical` : `positive`}>\n {editState.published ? (\n <Preview\n layout=\"default\"\n value={editState.published}\n schemaType={schema.get(editState.published._type) as SchemaType}\n />\n ) : (\n <Spinner />\n )}\n </Card>\n )\n}\n","import React, {useCallback} from 'react'\nimport {Box, Text, Stack, Button, useToast} from '@sanity/ui'\nimport {\n InputProps,\n Reference,\n SanityDocument,\n KeyedObject,\n TypedObject,\n useClient,\n useWorkspace,\n} from 'sanity'\nimport DocumentCheck from './DocumentCheck'\n\nexport type TranslationReference = KeyedObject & TypedObject & {value: Reference}\n\nexport type TranslationMetadataDocument = SanityDocument & {\n translations: TranslationReference[]\n schemaTypes: string[]\n}\n\nexport default function BulkPublish(props: InputProps) {\n const {translations} = props.value as TranslationMetadataDocument\n const client = useClient({apiVersion: `v2022-11-21`})\n const {projectId, dataset} = useWorkspace()\n const toast = useToast()\n const [invalidIds, setInvalidIds] = React.useState<string[]>([])\n\n const addId = useCallback((id: string) => {\n setInvalidIds((ids) => [...ids, id])\n }, [])\n\n const removeId = useCallback((id: string) => {\n setInvalidIds((ids) => ids.filter((i) => i !== id))\n }, [])\n\n const handleBulkPublish = useCallback(() => {\n const body = translations.map((translation) => ({documentId: translation.value._ref}))\n client\n .request({\n uri: `/publish/${projectId}/${dataset}`,\n method: 'POST',\n body,\n })\n .then((res) => {\n toast.push({\n status: 'success',\n title: 'Success',\n description: 'Bulk publish complete',\n })\n })\n .catch((err) => {\n console.error(err)\n toast.push({\n status: 'error',\n title: 'Error',\n description: 'Bulk publish failed',\n })\n })\n }, [translations, client, projectId, dataset, toast])\n\n // TODO: Hide all this if none of the documents have drafts\n return translations?.length > 0 ? (\n <Stack space={4}>\n <Stack space={3}>\n <Text weight=\"bold\" size={1}>\n Bulk publishing\n </Text>\n <Text>\n There{' '}\n {translations.length === 1 ? `is 1 document` : `are ${translations.length} documents`}.\n </Text>\n {invalidIds.length > 0 ? (\n <Text weight=\"medium\">\n {invalidIds.length === 1 ? `1 draft has` : `${invalidIds.length} drafts have`}{' '}\n validation issues that must addressed first.\n </Text>\n ) : (\n <Text>They are all valid.</Text>\n )}\n </Stack>\n <Stack space={2}>\n {translations.map((translation) => (\n <DocumentCheck\n key={translation._key}\n id={translation.value._ref}\n addId={addId}\n removeId={removeId}\n />\n ))}\n </Stack>\n <Button\n text={`Simultaneously Publish ${\n translations.length === 1 ? `1 Document` : `${translations.length} Documents`\n }`}\n onClick={handleBulkPublish}\n disabled={Boolean(invalidIds.length)}\n />\n </Stack>\n ) : null\n}\n","import React from 'react'\nimport {definePlugin, defineField} from 'sanity'\nimport {internationalizedArray} from 'sanity-plugin-internationalized-array'\nimport {Stack} from '@sanity/ui'\n\nimport metadata from './schema/translation/metadata'\nimport MenuButton from './components/MenuButton'\nimport {PluginConfig} from './types'\nimport {LanguageBadge} from './badges'\nimport {METADATA_SCHEMA_NAME} from './constants'\nimport BulkPublish from './components/BulkPublish'\n\nconst DEFAULT_CONFIG = {\n supportedLanguages: [],\n schemaTypes: [],\n languageField: `language`,\n bulkPublish: false,\n}\n\nexport const documentInternationalization = definePlugin<PluginConfig>((config) => {\n const {supportedLanguages, schemaTypes, languageField, bulkPublish} = {\n ...DEFAULT_CONFIG,\n ...config,\n }\n\n const renderLanguageFilter = (schemaType: string, documentId?: string) => {\n return (\n <MenuButton\n supportedLanguages={supportedLanguages}\n schemaType={schemaType}\n documentId={documentId ?? ``}\n languageField={languageField}\n />\n )\n }\n\n return {\n name: '@sanity/document-internationalization',\n\n // Adds:\n // - A bulk-publishing UI component to the form\n // - Will only work for projects on a compatible plan\n form: {\n components: {\n input: (props) => {\n if (\n bulkPublish &&\n props.id === 'root' &&\n props.schemaType.name === METADATA_SCHEMA_NAME\n ) {\n return (\n <Stack space={5}>\n <BulkPublish {...props} />\n {props.renderDefault(props)}\n </Stack>\n )\n }\n\n return props.renderDefault(props)\n },\n },\n },\n\n // Adds:\n // - The `Translations` dropdown to the editing form\n // - `Badges` to documents with a language value\n document: {\n unstable_languageFilter: (prev, ctx) => {\n const {schemaType, documentId} = ctx\n\n return schemaTypes.includes(schemaType)\n ? [...prev, () => renderLanguageFilter(schemaType, documentId)]\n : prev\n },\n badges: (prev, {schemaType}) => {\n if (!schemaTypes.includes(schemaType)) {\n return prev\n }\n\n return [(props) => LanguageBadge(props, supportedLanguages, languageField), ...prev]\n },\n },\n\n // Adds:\n // - The `Translations metadata` document type to the schema\n schema: {\n // Create the metadata document type\n types: [metadata(schemaTypes)],\n\n // For every schema type this plugin is enabled on\n // Create an initial value template to set the language\n templates: (prev, {schema}) => {\n const parameterizedTemplates = schemaTypes.map((schemaType) => ({\n id: `${schemaType}-parameterized`,\n title: `${schema?.get(schemaType)?.title ?? schemaType}: with Language`,\n schemaType,\n parameters: [{name: `languageId`, title: `Language ID`, type: `string`}],\n value: ({languageId}: {languageId: string}) => ({\n [languageField]: languageId,\n }),\n }))\n\n const staticTemplates = schemaTypes.flatMap((schemaType) => {\n return supportedLanguages.map((language) => ({\n id: `${schemaType}-${language.id}`,\n title: `${language.title} Lesson`,\n schemaType,\n value: {\n [languageField]: language.id,\n },\n }))\n })\n\n return [...prev, ...parameterizedTemplates, ...staticTemplates]\n },\n },\n\n // Uses:\n // - `sanity-plugin-internationalized-array` to maintain the translations array\n plugins: [\n // Translation metadata stores its references using this plugin\n // It cuts down on attribute usage and gives UI conveniences to add new translations\n internationalizedArray({\n languages: supportedLanguages,\n fieldTypes: [\n // TODO: The plugin should allow this kind of input\n // @ts-ignore\n defineField(\n {\n name: 'reference',\n type: 'reference',\n to: schemaTypes.map((type) => ({type: type})),\n // TODO: Add a validation rule to *ensure* the document's language matches the array key\n // Reference filters don't actually enforce validation!\n // validation: (Rule) => Rule.custom(),\n options: {\n collapsed: false,\n // TODO: Update type once it knows the values of this filter\n // @ts-ignore\n filter: ({parent, document}) => {\n if (!parent) return null\n\n // I'm not sure in what instance there's an array of parents\n // But the Type suggests it's possible\n const parentArray = Array.isArray(parent) ? parent : [parent]\n const language = parentArray.find((p) => p._key)\n\n if (!language?._key) return null\n\n if (document.schemaTypes) {\n return {\n filter: `_type in $schemaTypes && ${languageField} == $language`,\n params: {schemaTypes: document.schemaTypes, language: language._key},\n }\n }\n\n return {\n filter: `${languageField} == $language`,\n params: {language: language._key},\n }\n },\n },\n },\n {strict: false}\n ),\n ],\n }),\n ],\n }\n})\n","import {DocumentBadgeDescription, DocumentBadgeProps} from 'sanity'\n\nimport {Language} from '../types'\n\nexport function LanguageBadge(\n props: DocumentBadgeProps,\n supportedLanguages: Language[],\n languageField: string\n): DocumentBadgeDescription | null {\n const source = props?.draft || props?.published\n const languageId = source?.[languageField]\n const language = supportedLanguages.find((l) => l.id === languageId)\n\n if (!language) {\n return null\n }\n\n return {\n label: language.id,\n title: language.title,\n color: `primary`,\n }\n}\n"],"names":["metadata","schemaTypes","defineType","type","name","title","icon","TranslateIcon","liveEdit","fields","defineField","description","of","options","list","readOnly","_ref","value","Boolean","preview","select","translations","documentSchemaTypes","prepare","selection","length","languageKeys","map","t","_key","toUpperCase","join","subtitle","s","filter","useOpenInNewPane","id","routerContext","React","useContext","RouterContext","routerPanesState","groupIndex","usePaneRouter","useCallback","panes","splice","params","href","resolvePathFromState","navigateUrl","path","createReference","key","ref","_type","_weak","_strengthenOnPublish","LanguageOption","props","_a","index","language","languageField","schemaType","documentId","disabled","current","sourceId","sourceLanguageId","translation","client","useClient","toast","useToast","open","handleOpen","handleCreate","async","metadataExists","_id","transaction","documentIds","startsWith","replace","concat","newTranslationDocument","fetch","ids","uuid","create","metadataId","newTranslationReference","metadataPatch","patch","setIfMissing","insert","sourceReference","createIfNotExists","commit","then","push","status","catch","err","console","error","message","jsx","Button","onClick","mode","children","jsxs","Flex","gap","align","Spinner","Text","size","SplitVerticalIcon","CheckmarkIcon","AddIcon","Box","flex","Badge","tone","LanguageManage","text","CogIcon","LanguagePatch","source","handleClick","currentId","set","ChevronRightIcon","justify","MenuButton","supportedLanguages","setOpen","useState","o","button","setButton","popover","setPopover","handleClickOutside","useClickOutside","data","loading","useListeningQuery","translationSchema","useTranslationMetadata","draft","published","useEditState","sourceLanguageIsValid","some","l","content","overflow","Card","padding","Stack","space","Fragment","langIndex","find","Popover","constrainSize","portal","selected","DocumentCheck","addId","removeId","editState","validationStatus","useValidationStatus","schema","useSchema","validationHasErrors","useMemo","validation","item","level","useEffect","border","Preview","layout","get","BulkPublish","apiVersion","projectId","dataset","useWorkspace","invalidIds","setInvalidIds","i","handleBulkPublish","body","request","uri","method","res","weight","DEFAULT_CONFIG","bulkPublish","documentInternationalization","definePlugin","config","form","components","input","renderDefault","document","unstable_languageFilter","prev","ctx","includes","renderLanguageFilter","badges","_ref2","languageId","label","color","LanguageBadge","types","templates","_ref3","_b","parameters","_ref4","flatMap","plugins","internationalizedArray","languages","fieldTypes","to","collapsed","_ref5","parent","Array","isArray","p","strict"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/document-internationalization",
3
- "version": "2.0.0-studio-v3-plugin-v2.1",
3
+ "version": "2.0.0-studio-v3-plugin-v2.2",
4
4
  "description": "Create unique translations of a document based on its language, joined by a shared reference document.",
5
5
  "keywords": [
6
6
  "sanity",
@@ -51,7 +51,7 @@
51
51
  "@sanity/incompatible-plugin": "^1.0.4",
52
52
  "@sanity/ui": "1.0.0-beta.32",
53
53
  "@sanity/uuid": "^3.0.1",
54
- "sanity-plugin-internationalized-array": "^1.3.3",
54
+ "sanity-plugin-internationalized-array": "^1.4.1",
55
55
  "sanity-plugin-utils": "^1.0.0"
56
56
  },
57
57
  "devDependencies": {
package/src/plugin.tsx CHANGED
@@ -143,20 +143,20 @@ export const documentInternationalization = definePlugin<PluginConfig>((config)
143
143
  // I'm not sure in what instance there's an array of parents
144
144
  // But the Type suggests it's possible
145
145
  const parentArray = Array.isArray(parent) ? parent : [parent]
146
- const language = !parentArray.find((p) => p._key)?._key
146
+ const language = parentArray.find((p) => p._key)
147
147
 
148
- if (!language) return null
148
+ if (!language?._key) return null
149
149
 
150
150
  if (document.schemaTypes) {
151
151
  return {
152
152
  filter: `_type in $schemaTypes && ${languageField} == $language`,
153
- params: {schemaTypes: document.schemaTypes, language},
153
+ params: {schemaTypes: document.schemaTypes, language: language._key},
154
154
  }
155
155
  }
156
156
 
157
157
  return {
158
158
  filter: `${languageField} == $language`,
159
- params: {language},
159
+ params: {language: language._key},
160
160
  }
161
161
  },
162
162
  },