@@ -234,26 +234,20 @@ function deriveBagRecords(items: DataStore, templates: TemplateAdminRecord[], wi
234234function derivePluginRecords ( items : DataStore , templates : TemplateAdminRecord [ ] , wikis : WikiAdminRecord [ ] ) : PluginAdminRecord [ ] {
235235 const pluginUsage = new Map < string , Set < string > > ( ) ;
236236
237- const addUsage = ( pluginName : string , wikiName : string ) => {
238- if ( ! pluginName || ! wikiName ) return ;
239- const next = pluginUsage . get ( pluginName ) ?? new Set < string > ( ) ;
240- next . add ( wikiName ) ;
241- pluginUsage . set ( pluginName , next ) ;
242- } ;
243-
244237 for ( const wiki of wikis ) {
245238 const wikiName = wiki . slug || wiki . displayName || "" ;
246239 wiki . effectivePluginSet . forEach ( ( pluginValue ) => {
247240 const pluginName = pluginValue . split ( "@" ) [ 0 ] ?. trim ( ) ?? pluginValue . trim ( ) ;
248- addUsage ( pluginName , wikiName ) ;
241+ if ( ! pluginName || ! wikiName ) return ;
242+ mapGetInit ( pluginUsage , pluginName , ( ) => new Set < string > ( ) ) . add ( wikiName ) ;
249243 } ) ;
250244 }
251245
252246 return items . plugins . map ( ( plugin ) => {
253247 const usedByWikis = Array . from ( pluginUsage . get ( plugin . name ?? "" ) ?? [ ] ) ;
254248 return {
255249 ...plugin as unknown as PluginAdminRecord ,
256- usedByWikis : usedByWikis . join ( "\n" ) ,
250+ usedByWikis,
257251 usageCount : String ( usedByWikis . length ) ,
258252 } ;
259253 } ) ;
@@ -745,77 +739,6 @@ function getListColumnLink(tabId: TabId, columnKey: string, item: AdminRecord):
745739 return mapper ? mapper ( item ) : null ;
746740}
747741
748- function countValueLines ( value : readonly string [ ] ) : number {
749- return value . length ;
750- }
751-
752- function getSidebarFacts ( tabId : TabId , draft : AdminRecord ) : Array < { label : string ; value : string ; } > ;
753- function getSidebarFacts ( tabId : TabId , draft : unknown ) : Array < { label : string ; value : string ; } > {
754- if ( tabId === "wikis" ) {
755- definitely < WikiAdminRecord > ( draft ) ;
756- return [
757- { label : "Template" , value : formatFieldValue ( draft . templateName || draft . templateRef ?. name ) } ,
758- { label : "Default bag" , value : formatFieldValue ( draft . defaultWritableBag ) } ,
759- { label : "Compiled" , value : formatFieldValue ( draft . lastCompiledAt ) } ,
760- ] ;
761- }
762-
763- if ( tabId === "templates" ) {
764- definitely < TemplateAdminRecord > ( draft ) ;
765- return [
766- { label : "Readonly bags" , value : String ( ( draft . readonlyBags . length ) ) } ,
767- { label : "Prefix rules" , value : String ( draft . writablePrefixBags . length || 0 ) } ,
768- { label : "Default bag" , value : formatFieldValue ( draft . defaultWritableBag ) } ,
769- { label : "Plugins" , value : String ( draft . plugins . length ) } ,
770- { label : "Validation" , value : formatFieldValue ( draft . validationStatus || draft . validationReport ) } ,
771- ] ;
772- }
773-
774- if ( tabId === "bags" ) {
775- definitely < BagAdminRecord > ( draft ) ;
776- return [
777- { label : "Permission roles" , value : String ( draft . permissions . length || 0 ) } ,
778- { label : "Referenced by templates" , value : String ( draft . referencedByTemplates . length ) } ,
779- { label : "Referenced by wikis" , value : String ( draft . referencedByWikis . length ) } ,
780- { label : "Routing roles" , value : String ( draft . referencedByWikis . length ) } ,
781- // { label: "Tiddlers", value: formatFieldValue(draft.tiddlerCount) },
782- // { label: "Last activity", value: formatFieldValue(draft.lastActivityAt) },
783- ] ;
784- }
785-
786- if ( tabId === "plugins" ) {
787- definitely < PluginAdminRecord > ( draft ) ;
788- return [
789- { label : "Version" , value : formatFieldValue ( draft . version ) } ,
790- { label : "Status" , value : formatFieldValue ( draft . status ) } ,
791- { label : "Used by wikis" , value : String ( draft . usedByWikis . length ) } ,
792- { label : "Usage count" , value : formatFieldValue ( draft . usageCount ) } ,
793- { label : "Draft of" , value : formatFieldValue ( draft . draftOf ) } ,
794- { label : "Updated" , value : formatFieldValue ( draft . updatedAt ) } ,
795- ] ;
796- }
797-
798- if ( tabId === "roles" ) {
799- definitely < RoleAdminRecord > ( draft ) ;
800- return [
801- { label : "Role name" , value : formatFieldValue ( draft . roleId ) } ,
802- { label : "Description" , value : formatFieldValue ( draft . description ) } ,
803- ] ;
804- }
805-
806- if ( tabId === "users" ) {
807- definitely < UserAdminRecord > ( draft ) ;
808- return [
809- { label : "Username" , value : formatFieldValue ( draft . username ) } ,
810- { label : "Email" , value : formatFieldValue ( draft . email ) } ,
811- { label : "Assigned roles" , value : String ( draft . userRoles . length ) } ,
812- ] ;
813- }
814-
815- { const t : never = tabId ; return [ ] ; }
816-
817- }
818-
819742function renderSearchableInput ( { id, currentValue, placeholder, options, onInput, disabled } : {
820743 id : string ;
821744 currentValue : string ;
@@ -890,15 +813,15 @@ function renderActivityFeedField(ctx: ReadonlyFieldContext<readonly string[]>) {
890813}
891814
892815function renderMetadataTableField ( ctx : ReadonlyFieldContext < readonly string [ ] > ) {
893- const lines = ctx . value ;
816+ const lines = ctx . saved ;
894817 return < dl class = "meta-list" > { lines . map ( ( line ) => {
895818 const [ key , ...rest ] = line . split ( ":" ) ;
896819 return < > < dt > { key } </ dt > < dd > { rest . join ( ":" ) . trim ( ) } </ dd > </ > ;
897820 } ) } </ dl > ;
898821}
899822
900823function renderTableField ( ctx : ReadonlyFieldContext ) {
901- const { field, value, itemsByTab } = ctx ;
824+ const { field, saved : value , itemsByTab } = ctx ;
902825 definitely < readonly string [ ] > ( value ) ;
903826 const lines = value ;
904827 const missingDependencyLines = getMissingDependencyLines ( field , value , itemsByTab ) ;
@@ -934,8 +857,8 @@ function renderTableField(ctx: ReadonlyFieldContext) {
934857}
935858
936859function renderCalloutField ( ctx : ReadonlyFieldContext ) {
937- definitely < string > ( ctx . value ) ;
938- return < div class = "field-callout" > < p > { formatFieldValue ( ctx . value ) } </ p > </ div > ;
860+ definitely < string > ( ctx . saved ) ;
861+ return < div class = "field-callout" > < p > { formatFieldValue ( ctx . saved ) } </ p > </ div > ;
939862}
940863
941864function renderPreField ( ctx : ReadonlyFieldContext ) {
@@ -1020,7 +943,7 @@ class SearchMultiselectFieldHandler extends FieldTypeHandler<string[]> {
1020943
1021944 public override renderSidebar ( ctx : ReadonlyFieldContext < readonly string [ ] > ) : JSX . Node {
1022945 return < ul >
1023- { ctx . value . map ( e => < li > { e } </ li > ) }
946+ { ctx . saved . map ( e => < li > { e } </ li > ) }
1024947 </ ul >
1025948 }
1026949
@@ -1293,7 +1216,7 @@ class AutocompleteFieldHandler extends FieldTypeHandler<Reference | null> {
12931216 }
12941217
12951218 renderSidebar ( ctx : ReadonlyFieldContext < Reference | null > ) {
1296- return ctx . value ?. name ?? "" ;
1219+ return ctx . saved ?. name ?? "" ;
12971220 }
12981221
12991222 public override renderEditor ( ctx : FieldEditorContext < Reference | null > ) {
@@ -1392,15 +1315,16 @@ class ValueListFieldHandler extends FieldTypeHandler<string[]> {
13921315
13931316 public override renderSidebar ( ctx : ReadonlyFieldContext ) {
13941317 // TODO: string should probably be a separate class
1395- const lines = typeof ctx . value === "string"
1396- ? lineListCodec . parse ( ctx . value )
1397- : ctx . value as readonly string [ ] ;
1318+ const lines = typeof ctx . saved === "string"
1319+ ? lineListCodec . parse ( ctx . saved )
1320+ : ctx . saved as readonly string [ ] ;
13981321 return < ul class = "value-list" > { lines . map ( ( line ) => < li > { line } </ li > ) } </ ul > ;
13991322 }
14001323
14011324 public override renderEditor ( ctx : FieldEditorContext ) {
14021325 return this . renderSidebar ( ctx ) ;
14031326 }
1327+
14041328}
14051329
14061330class ActivityFeedFieldHandler extends FieldTypeHandler < readonly string [ ] > {
@@ -1793,10 +1717,14 @@ class RecordModalElement extends JSXElement {
17931717 ) ;
17941718 } ) }
17951719
1796- < footer class = "modal-actions" >
1797- < button class = "ghost-button" type = "button" onclick = { onClose } disabled = { isSaving } > Cancel</ button >
1798- < button class = "primary-button" type = "button" onclick = { onSave } disabled = { isSaving || isOpeningItem } > { isSaving ? "Saving..." : modalState . mode === "create" ? `Save ${ selectedTab . label . slice ( 0 , - 1 ) } ` : "Save changes" } </ button >
1799- </ footer >
1720+ { modalState . tabId !== "plugins"
1721+ ? < footer class = "modal-actions" >
1722+ < button class = "ghost-button" type = "button" onclick = { onClose } disabled = { isSaving } > Cancel</ button >
1723+ < button class = "primary-button" type = "button" onclick = { onSave } disabled = { isSaving || isOpeningItem } > { isSaving ? "Saving..." : modalState . mode === "create" ? `Save ${ selectedTab . label . slice ( 0 , - 1 ) } ` : "Save changes" } </ button >
1724+ </ footer >
1725+ : < footer class = "modal-actions" >
1726+ < button class = "ghost-button" type = "button" onclick = { onClose } disabled = { isSaving } > Close</ button >
1727+ </ footer > }
18001728 </ div >
18011729 </ div >
18021730 ) }
0 commit comments