Skip to content

Commit a1698dd

Browse files
authored
Initial configuration state if adaptive content is not enabled (#852)
* Add initial state when adaptive content is not enabled * skip if not enabled * changeset
1 parent 0d5e332 commit a1698dd

File tree

13 files changed

+277
-73
lines changed

13 files changed

+277
-73
lines changed

.changeset/thick-geckos-push.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@gitbook/integration-launchdarkly': minor
3+
'@gitbook/integration-bucket': minor
4+
---
5+
6+
Initial configuration state if adaptive content is not enabled

integrations/bucket/gitbook-manifest.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ icon: ./assets/icon.png
1818
previewImages:
1919
- ./assets/preview.png
2020
scopes:
21+
- site:metadata:read
22+
- site:views:read
2123
- site:adaptive:read
2224
- site:adaptive:write
2325
visibility: private

integrations/bucket/src/components.tsx

Lines changed: 61 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
BucketSiteInstallationConfiguration,
77
BucketState,
88
} from './types';
9-
import { assertSiteInstallation } from './utils';
9+
import { assertInstallation, assertSiteInstallation } from './utils';
1010

1111
export const configBlock = createComponent<
1212
BucketProps,
@@ -53,41 +53,68 @@ export const configBlock = createComponent<
5353
return { type: 'complete' };
5454
}
5555
},
56-
render: async () => {
56+
render: async (element, context) => {
57+
const installation = assertInstallation(context.environment);
58+
const siteInstallation = assertSiteInstallation(context.environment);
59+
60+
const { data: site } = await context.api.orgs.getSiteById(
61+
installation.target.organization,
62+
siteInstallation.site,
63+
);
64+
const isAdaptiveContentEnabled = Boolean(site.adaptiveContent?.enabled);
65+
5766
return (
58-
<block>
59-
<input
60-
label="Secret key"
61-
hint={
62-
<text>
63-
The secret key from your Bucket{' '}
64-
<link
65-
target={{
66-
url: 'https://app.bucket.co/envs/current/settings/app-environments',
67-
}}
68-
>
69-
environment settings.
70-
</link>
71-
</text>
72-
}
73-
element={<textinput state="secret_key" placeholder="Secret key" />}
74-
/>
75-
<input
76-
label=""
77-
hint=""
78-
element={
79-
<button
80-
style="primary"
81-
disabled={false}
82-
label="Save"
83-
tooltip="Save configuration"
84-
onPress={{
85-
action: 'save.config',
86-
}}
67+
<configuration>
68+
{isAdaptiveContentEnabled ? (
69+
<block>
70+
<input
71+
label="Secret key"
72+
hint={
73+
<text>
74+
The secret key from your Bucket{' '}
75+
<link
76+
target={{
77+
url: 'https://app.bucket.co/envs/current/settings/app-environments',
78+
}}
79+
>
80+
environment settings.
81+
</link>
82+
</text>
83+
}
84+
element={<textinput state="secret_key" placeholder="Secret key" />}
85+
/>
86+
<input
87+
label=""
88+
hint=""
89+
element={
90+
<button
91+
style="primary"
92+
disabled={false}
93+
label="Save"
94+
tooltip="Save configuration"
95+
onPress={{
96+
action: 'save.config',
97+
}}
98+
/>
99+
}
87100
/>
88-
}
89-
/>
90-
</block>
101+
</block>
102+
) : (
103+
<input
104+
label="Enable Adaptive Content"
105+
hint="To use Bucket, you need to enable Adaptive Content in your site audience settings."
106+
element={
107+
<button
108+
label="Enable"
109+
onPress={{
110+
action: '@ui.url.open',
111+
url: `${site.urls.app}/settings/audience`,
112+
}}
113+
/>
114+
}
115+
/>
116+
)}
117+
</configuration>
91118
);
92119
},
93120
});

integrations/bucket/src/index.tsx

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
} from '@gitbook/runtime';
99
import { arrayToHex, assertSiteInstallation, safeCompare } from './utils';
1010
import { type BucketRuntimeContext, type IntegrationTask } from './types';
11-
import { handleIntegrationTask } from './tasks';
11+
import { handleIntegrationTask, SYNC_ADAPTIVE_SCHEMA_SCHEDULE_SECONDS } from './tasks';
1212
import { configBlock } from './components';
1313

1414
const logger = Logger('bucket');
@@ -96,6 +96,43 @@ export default createIntegration({
9696
fetch: handleFetchEvent,
9797
components: [configBlock],
9898
events: {
99+
site_view: async (event, context) => {
100+
const siteInstallation = assertSiteInstallation(context.environment);
101+
// If the last sync was more than an hour ago, we trigger a sync
102+
if (
103+
!siteInstallation.configuration.lastSync ||
104+
siteInstallation.configuration.lastSync <
105+
Date.now() - SYNC_ADAPTIVE_SCHEMA_SCHEDULE_SECONDS * 1000
106+
) {
107+
const api = new GitBookAPI({
108+
authToken: context.environment.apiTokens.integration,
109+
endpoint: context.environment.apiEndpoint,
110+
userAgent: context.api.userAgent,
111+
});
112+
113+
const organizationId = context.environment.installation?.target.organization;
114+
if (!organizationId) {
115+
throw new Error(
116+
`No organization ID found in the installation ${event.installationId}`,
117+
);
118+
}
119+
120+
await handleIntegrationTask(
121+
{
122+
...context,
123+
api,
124+
},
125+
{
126+
type: 'sync-adaptive-schema',
127+
payload: {
128+
siteId: event.siteId,
129+
installationId: event.installationId,
130+
organizationId,
131+
},
132+
},
133+
);
134+
}
135+
},
99136
site_installation_setup: async (event, context) => {
100137
const api = new GitBookAPI({
101138
authToken: context.environment.apiTokens.integration,

integrations/bucket/src/tasks.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import { GitBookAPI, GitBookAPIError, type SiteAdaptiveJSONSchema } from '@gitbo
88

99
const logger = Logger('bucket:tasks');
1010

11+
export const SYNC_ADAPTIVE_SCHEMA_SCHEDULE_SECONDS = 3600; // 1 hour
12+
1113
export async function handleIntegrationTask(
1214
context: BucketRuntimeContext,
1315
task: IntegrationTask,
@@ -20,7 +22,7 @@ export async function handleIntegrationTask(
2022
context.environment.integration.name,
2123
{
2224
task,
23-
schedule: 3600,
25+
schedule: SYNC_ADAPTIVE_SCHEMA_SCHEDULE_SECONDS,
2426
},
2527
),
2628
]);
@@ -68,6 +70,14 @@ async function handleSyncAdaptiveSchema(
6870
throw new Error(`No secret key configured in the site installation ${siteId}`);
6971
}
7072

73+
const { data: site } = await api.orgs.getSiteById(organizationId, siteId);
74+
if (!site.adaptiveContent?.enabled) {
75+
logger.info(
76+
`Adaptive content is not enabled for site ${siteId}, skipping adaptive schema sync.`,
77+
);
78+
return;
79+
}
80+
7181
const [existing, featureFlags] = await Promise.all([
7282
getExistingAdaptiveSchema(api, organizationId, siteId),
7383
getFeatureFlags(secretKey),
@@ -120,6 +130,20 @@ async function handleSyncAdaptiveSchema(
120130
},
121131
},
122132
});
133+
134+
logger.info(`Updated adaptive schema for site ${siteId} in installation ${installationId}`);
135+
// Update the site installation to mark the last sync time
136+
await context.api.integrations.updateIntegrationSiteInstallation(
137+
integrationName,
138+
installationId,
139+
siteId,
140+
{
141+
configuration: {
142+
...siteInstallation.configuration,
143+
lastSync: Date.now(),
144+
},
145+
},
146+
);
123147
} catch (error) {
124148
logger.error(`Error while handling adaptive schema sync: ${error}`);
125149
throw error;

integrations/bucket/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { RuntimeContext, RuntimeEnvironment } from '@gitbook/runtime';
22

33
export type BucketSiteInstallationConfiguration = {
44
secret_key?: string;
5+
lastSync?: number;
56
};
67

78
export type BucketRuntimeEnvironment = RuntimeEnvironment<{}, BucketSiteInstallationConfiguration>;

integrations/bucket/src/utils.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,12 @@ export function assertSiteInstallation(environment: BucketRuntimeEnvironment) {
3434

3535
return siteInstallation;
3636
}
37+
38+
export function assertInstallation(environment: BucketRuntimeEnvironment) {
39+
const installation = environment.installation;
40+
if (!installation) {
41+
throw new Error('No installation found');
42+
}
43+
44+
return installation;
45+
}

integrations/launchdarkly/gitbook-manifest.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ icon: ./assets/icon.png
1818
previewImages:
1919
- ./assets/preview.png
2020
scopes:
21+
- site:metadata:read
22+
- site:views:read
2123
- site:adaptive:read
2224
- site:adaptive:write
2325
visibility: private

integrations/launchdarkly/src/components.tsx

Lines changed: 60 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
LaunchDarklySiteInstallationConfiguration,
77
LaunchDarklyState,
88
} from './types';
9-
import { assertSiteInstallation } from './utils';
9+
import { assertInstallation, assertSiteInstallation } from './utils';
1010

1111
export const configBlock = createComponent<
1212
LaunchDarklyProps,
@@ -62,41 +62,67 @@ export const configBlock = createComponent<
6262
return { type: 'complete' };
6363
}
6464
},
65-
render: async () => {
65+
render: async (element, context) => {
66+
const installation = assertInstallation(context.environment);
67+
const siteInstallation = assertSiteInstallation(context.environment);
68+
69+
const { data: site } = await context.api.orgs.getSiteById(
70+
installation.target.organization,
71+
siteInstallation.site,
72+
);
73+
const isAdaptiveContentEnabled = Boolean(site.adaptiveContent?.enabled);
6674
return (
67-
<block>
68-
<input
69-
label="Secret key"
70-
hint={
71-
<text>
72-
The secret key from your LaunchDarkly{' '}
73-
<link
74-
target={{
75-
url: 'https://app.LaunchDarkly.co/envs/current/settings/app-environments',
76-
}}
77-
>
78-
environment settings.
79-
</link>
80-
</text>
81-
}
82-
element={<textinput state="secret_key" placeholder="Secret key" />}
83-
/>
84-
<input
85-
label=""
86-
hint=""
87-
element={
88-
<button
89-
style="primary"
90-
disabled={false}
91-
label="Save"
92-
tooltip="Save configuration"
93-
onPress={{
94-
action: 'save.config',
95-
}}
75+
<configuration>
76+
{isAdaptiveContentEnabled ? (
77+
<block>
78+
<input
79+
label="Secret key"
80+
hint={
81+
<text>
82+
The secret key from your LaunchDarkly{' '}
83+
<link
84+
target={{
85+
url: 'https://app.LaunchDarkly.co/envs/current/settings/app-environments',
86+
}}
87+
>
88+
environment settings.
89+
</link>
90+
</text>
91+
}
92+
element={<textinput state="secret_key" placeholder="Secret key" />}
9693
/>
97-
}
98-
/>
99-
</block>
94+
<input
95+
label=""
96+
hint=""
97+
element={
98+
<button
99+
style="primary"
100+
disabled={false}
101+
label="Save"
102+
tooltip="Save configuration"
103+
onPress={{
104+
action: 'save.config',
105+
}}
106+
/>
107+
}
108+
/>
109+
</block>
110+
) : (
111+
<input
112+
label="Enable Adaptive Content"
113+
hint="To use LaunchDarkly, you need to enable Adaptive Content in your site audience settings."
114+
element={
115+
<button
116+
label="Enable"
117+
onPress={{
118+
action: '@ui.url.open',
119+
url: `${site.urls.app}/settings/audience`,
120+
}}
121+
/>
122+
}
123+
/>
124+
)}
125+
</configuration>
100126
);
101127
},
102128
});

0 commit comments

Comments
 (0)