11import type React from "react" ;
2- import { useState , useEffect , useCallback } from "react" ;
3- import { isEmpty , isNil } from "lodash" ;
4- import "../baseStyles.css" ;
2+ import { useState , useEffect , useMemo } from "react" ;
3+ import { isNil } from "lodash" ;
54import { usePluginContext } from "@cortexapps/plugin-core/components" ;
6- import { getEntityYaml } from "../api/Cortex" ;
7- import { getConfluenceDetailsFromEntity } from "../lib/parseEntity" ;
85import { Heading , Box } from "@chakra-ui/react" ;
6+
97import Instructions from "./Instructions" ;
108import Loading from "./Loading" ;
119import Notice from "./Notice" ;
1210import PageSelector from "./PageSelector" ;
13- import { fetchConfluencePageContent } from "../api/fetchConfluencePageContent" ;
14- import { fetchConfluencePluginConfig } from "../api/fetchConfluencePluginConfig" ;
11+
12+ import {
13+ usePluginConfig ,
14+ useCortexEntityDefinition ,
15+ useConfluencePageContent ,
16+ } from "../hooks" ;
17+
18+ import "../baseStyles.css" ;
1519
1620const PageContent : React . FC = ( ) => {
17- const [ entityPages , setEntityPages ] = useState < EntityPageI [ ] > ( [ ] ) ;
18- const [ pageContent , setPageContent ] = useState < string | undefined > ( ) ;
19- const [ pageTitle , setPageTitle ] = useState < string | undefined > ( ) ;
20- const [ entityPage , setEntityPage ] = useState < string | number | undefined > ( ) ;
21- const [ baseConfluenceUrl , setBaseConfluenceUrl ] = useState < string > ( "" ) ;
21+ const [ entityPage , setEntityPage ] = useState < EntityPageI > ( ) ;
2222 const [ errorStr , setErrorStr ] = useState < string > ( "" ) ;
2323
2424 const context = usePluginContext ( ) ;
2525
26- const fetchPageContent = useCallback (
27- async ( pages : EntityPageI [ ] , pageId : string | number ) : Promise < void > => {
28- if ( pages . length === 0 ) return ;
29- setEntityPage ( pageId ) ;
30- setErrorStr ( "loading-content" ) ;
31- try {
32- const contentJSON = await fetchConfluencePageContent (
33- baseConfluenceUrl ,
34- pageId
35- ) ;
36- setPageContent ( contentJSON . body . view . value ) ;
37- setPageTitle ( contentJSON . title ) ;
38- setErrorStr ( "" ) ;
39- } catch ( error ) {
40- setErrorStr ( error . message ) ;
41- }
42- } ,
43- [ baseConfluenceUrl ]
26+ const { isLoading : isPluginConfigLoading , pluginConfig } = usePluginConfig (
27+ "confluence-plugin-config"
4428 ) ;
4529
46- const fetchMissingPageTitles = useCallback (
47- async ( pages : EntityPageI [ ] ) : Promise < EntityPageI [ ] > => {
48- if ( pages . length === 0 ) return [ ] ;
49- const updatedPages = await Promise . all (
50- pages . map ( async ( page ) => {
51- if ( page . title && page . title . length > 0 ) {
52- return page ;
53- }
54- try {
55- const contentJSON = await fetchConfluencePageContent (
56- baseConfluenceUrl ,
57- page . id
58- ) ;
59- return {
60- ...page ,
61- title :
62- page . title && page . title . length > 0
63- ? page . title
64- : contentJSON . title ,
65- } ;
66- } catch ( error ) {
67- console . error (
68- `Error fetching page title for page with ID ${ page . id } : ${
69- ( error as Error ) . message
70- } `
71- ) ;
72- return page ;
73- }
74- } )
75- ) ;
76- return updatedPages ;
77- } ,
78- [ baseConfluenceUrl ]
30+ const { isLoading : isEntityDefinitionLoading , entityDefinition } =
31+ useCortexEntityDefinition ( context . entity ?. tag ?? "" ) ;
32+
33+ const baseConfluenceUrl = useMemo (
34+ ( ) => pluginConfig ?. info ?. [ "x-cortex-definition" ] ?. [ "confluence-url" ] ?? "" ,
35+ [ pluginConfig ]
7936 ) ;
8037
81- useEffect ( ( ) => {
82- if ( ! context ?. apiBaseUrl ) return ;
83- const getConfig = async ( ) : Promise < void > => {
84- setErrorStr ( "loading" ) ;
85- try {
86- const newConfluenceUrl = await fetchConfluencePluginConfig (
87- context . apiBaseUrl
88- ) ;
89- setBaseConfluenceUrl ( newConfluenceUrl ) ;
90- setErrorStr ( ! newConfluenceUrl ? "instructions" : "" ) ;
91- } catch {
92- setErrorStr ( "instructions" ) ;
38+ const entityPages = useMemo ( ( ) : EntityPageI [ ] => {
39+ if ( ! entityDefinition ) return [ ] ;
40+ const entityPages : EntityPageI [ ] = [ ] ;
41+ if ( Array . isArray ( entityDefinition . info ?. [ "x-cortex-confluence" ] ?. pages ) ) {
42+ for ( const page of entityDefinition . info [ "x-cortex-confluence" ] . pages ) {
43+ const id = page . id as string ;
44+ const title = page . title as string ;
45+ if ( id ) {
46+ entityPages . push ( { id, title } ) ;
47+ }
9348 }
94- } ;
95- void getConfig ( ) ;
96- } , [ context ?. apiBaseUrl ] ) ;
49+ }
50+ if ( entityDefinition . info ?. [ "x-cortex-confluence" ] ?. pageID ) {
51+ entityPages . push ( {
52+ id : `${ entityDefinition . info [ "x-cortex-confluence" ] . pageID as string } ` ,
53+ } ) ;
54+ }
55+ return entityPages ;
56+ } , [ entityDefinition ] ) ;
57+
58+ useEffect ( ( ) => {
59+ if ( entityPages . length > 0 && ! entityPage ) {
60+ setEntityPage ( entityPages [ 0 ] ) ;
61+ }
62+ } , [ entityPages , entityPage ] ) ;
63+
64+ const { isLoading : isContentLoading , contents } =
65+ useConfluencePageContent ( entityPages ) ;
66+
67+ const isLoading = useMemo (
68+ ( ) =>
69+ isPluginConfigLoading || isEntityDefinitionLoading || isContentLoading ,
70+ [ isPluginConfigLoading , isEntityDefinitionLoading , isContentLoading ]
71+ ) ;
9772
9873 useEffect ( ( ) => {
9974 if ( ! context . entity ?. tag ) {
10075 setErrorStr (
101- "This plugin is intended to be used within the entities. " +
76+ "This plugin is intended to be used within entities. " +
10277 "Go to an entity, then under Plugins, select Confluence to view the Confluence page(s)."
10378 ) ;
10479 }
80+ } , [ context . entity ?. tag ] ) ;
10581
106- if ( ! context . apiBaseUrl || ! baseConfluenceUrl ) {
107- return ;
108- }
109-
110- const fetchEntityYamlData = async ( ) : Promise < void > => {
111- const entityTag = context . entity ?. tag ;
112- if ( ! isNil ( entityTag ) ) {
113- try {
114- setErrorStr ( "loading" ) ;
115- const yaml = await getEntityYaml ( context . apiBaseUrl , entityTag ) ;
116- const fetchedEntityPages = isEmpty ( yaml )
117- ? [ ]
118- : getConfluenceDetailsFromEntity ( yaml ) ;
119- if ( fetchedEntityPages . length === 0 ) {
120- setErrorStr ( "No Confluence details exist on this entity." ) ;
121- return ;
122- }
123- const pagesWithTitles = await fetchMissingPageTitles (
124- fetchedEntityPages
125- ) ;
126- setEntityPages ( pagesWithTitles ) ;
127- } catch ( error ) {
128- setErrorStr (
129- `Error retrieving Confluence page: ${ ( error as Error ) . message } `
130- ) ;
131- console . error ( "Error retrieving Confluence page: " , error ) ;
132- }
133- }
134- } ;
135- void fetchEntityYamlData ( ) ;
136- } , [
137- context . apiBaseUrl ,
138- context . entity ?. tag ,
139- baseConfluenceUrl ,
140- fetchMissingPageTitles ,
141- ] ) ;
142-
143- useEffect ( ( ) => {
144- const setFirstPageContent = async ( ) : Promise < void > => {
145- if ( entityPages . length === 0 ) return ;
146- await fetchPageContent ( entityPages , entityPages [ 0 ] . id ) ;
147- } ;
148- void setFirstPageContent ( ) ;
149- } , [ baseConfluenceUrl , entityPages , fetchPageContent ] ) ;
150-
151- if ( errorStr === "loading" ) return < Loading /> ;
152- if ( errorStr === "instructions" ) return < Instructions /> ;
153- if ( errorStr && errorStr !== "loading-content" )
154- return < Notice > { errorStr } </ Notice > ;
82+ if ( isLoading ) return < Loading /> ;
83+ if ( ! baseConfluenceUrl ) return < Instructions /> ;
84+ if ( errorStr ) return < Notice > { errorStr } </ Notice > ;
15585
15686 if ( isNil ( entityPage ) ) {
15787 return (
15888 < Notice >
159- We could not find any Confluence page associated with this entity.
89+ We could not find any Confluence pages associated with this entity.
16090 </ Notice >
16191 ) ;
16292 }
@@ -165,26 +95,42 @@ const PageContent: React.FC = () => {
16595 < Box w = "full" minH = { 600 } >
16696 { entityPages . length > 1 && (
16797 < PageSelector
168- currentPageId = { entityPage }
169- onChangeHandler = { fetchPageContent }
98+ currentPageId = { entityPage . id }
99+ onChangeHandler = { ( pageId : string ) => {
100+ const newEntityPage = entityPages . find (
101+ ( page ) => `${ page . id as string } ` === pageId
102+ ) ;
103+ if ( newEntityPage ) setEntityPage ( newEntityPage ) ;
104+ } }
170105 pages = { entityPages }
171- disabled = { errorStr === "loading-content" }
106+ disabled = { isContentLoading }
172107 />
173108 ) }
174- { errorStr === "loading-content" ? (
175- < Loading />
176- ) : (
177- < Box w = "full" >
178- < Heading
179- as = "h1"
180- dangerouslySetInnerHTML = { { __html : pageTitle as string } }
181- />
109+ < Box w = "full" >
110+ < Heading
111+ as = "h1"
112+ dangerouslySetInnerHTML = { {
113+ __html : contents [ ` ${ entityPage . id } ` ] ?. title as string ,
114+ } }
115+ />
116+ { contents [ ` ${ entityPage . id } ` ] ?. body && (
182117 < Box
183118 w = "full"
184- dangerouslySetInnerHTML = { { __html : pageContent as string } }
119+ dangerouslySetInnerHTML = { {
120+ __html : contents [ `${ entityPage . id } ` ] ?. body as string ,
121+ } }
185122 />
186- </ Box >
187- ) }
123+ ) }
124+ { contents [ `${ entityPage . id } ` ] ?. errors && (
125+ < Notice >
126+ { contents [ `${ entityPage . id } ` ] ?. errors . map ( ( error : any ) => (
127+ < Box display = "block" key = { error . code } >
128+ { error . title }
129+ </ Box >
130+ ) ) }
131+ </ Notice >
132+ ) }
133+ </ Box >
188134 </ Box >
189135 ) ;
190136} ;
0 commit comments