Skip to content

Commit c636c84

Browse files
feat: additional changes for implementation of new preview command (#1167)
* feat: additional changes for implementation of new preview command * feat: changes for the new preview command done. * chore: add changeset --------- Co-authored-by: Ashish Padhy <ashishpadhy1729@gmail.com>
1 parent 35b3495 commit c636c84

File tree

6 files changed

+168
-53
lines changed

6 files changed

+168
-53
lines changed

.changeset/honest-candles-brush.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@asyncapi/studio": patch
3+
---
4+
5+
feat: additional changes for implementation of new preview command

apps/studio/src/components/Modals/ConvertToLatestModal.tsx

Lines changed: 53 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { create } from '@ebay/nice-modal-react';
55
import { ConfirmModal } from './ConfirmModal';
66

77
import { useServices } from '../../services';
8-
import { useDocumentsState } from '../../state';
8+
import { useDocumentsState,appState } from '../../state';
99

1010
interface ConvertToLatestModal {
1111
convertOnlyToLatest: boolean
@@ -57,55 +57,57 @@ export const ConvertToLatestModal = create<ConvertToLatestModal>(({ convertOnlyT
5757
content = 'There is a new version of AsyncAPI. Convert your document to newest version if you want.';
5858
}
5959

60-
return (
61-
<ConfirmModal
62-
title={convertOnlyToLatest ? 'Convert AsyncAPI document to latest version' : 'Convert AsyncAPI document to newest version'}
63-
confirmText={convertOnlyToLatest ? `Convert to ${latestVersion}` : 'Convert'}
64-
confirmDisabled={false}
65-
onSubmit={onSubmit}
66-
>
67-
<div className="flex flex-col content-center justify-center text-center">
68-
<p>
69-
{content}
70-
</p>
71-
<ul className="mt-4">
72-
{reservedAllowedVersions.map(v => v !== '2.0.0' && (
73-
<li key={v}>
74-
<a
75-
className="underline"
76-
href={`https://www.asyncapi.com/blog/release-notes-${v}`}
77-
target="_blank"
78-
rel="nofollow noopener noreferrer"
60+
if (!appState.getState().readOnly) {
61+
return (
62+
<ConfirmModal
63+
title={convertOnlyToLatest ? 'Convert AsyncAPI document to latest version' : 'Convert AsyncAPI document to newest version'}
64+
confirmText={convertOnlyToLatest ? `Convert to ${latestVersion}` : 'Convert'}
65+
confirmDisabled={false}
66+
onSubmit={onSubmit}
67+
>
68+
<div className="flex flex-col content-center justify-center text-center">
69+
<p>
70+
{content}
71+
</p>
72+
<ul className="mt-4">
73+
{reservedAllowedVersions.map(v => v !== '2.0.0' && (
74+
<li key={v}>
75+
<a
76+
className="underline"
77+
href={`https://www.asyncapi.com/blog/release-notes-${v}`}
78+
target="_blank"
79+
rel="nofollow noopener noreferrer"
80+
>
81+
See the release notes for {v}
82+
</a>
83+
</li>
84+
))}
85+
</ul>
86+
{convertOnlyToLatest === false ? (
87+
<div className="flex content-center justify-center mt-4">
88+
<label
89+
htmlFor="asyncapi-version"
90+
className="flex justify-right items-center w-1/2 content-center font-medium text-gray-700"
7991
>
80-
See the release notes for {v}
81-
</a>
82-
</li>
83-
))}
84-
</ul>
85-
{convertOnlyToLatest === false ? (
86-
<div className="flex content-center justify-center mt-4">
87-
<label
88-
htmlFor="asyncapi-version"
89-
className="flex justify-right items-center w-1/2 content-center font-medium text-gray-700"
90-
>
91-
To version:
92-
</label>
93-
<select
94-
name="asyncapi-version"
95-
className="shadow-sm focus:ring-pink-500 focus:border-pink-500 w-1/2 block w-full sm:text-sm border-gray-300 rounded-md py-2 px-1 text-gray-700 border-pink-300 border-2"
96-
onChange={e => setVersion(e.target.value)}
97-
value={version}
98-
>
99-
<option value={latestVersion} key={latestVersion}>{latestVersion} (latest)</option>
100-
{reservedAllowedVersions.filter((v) => v !== latestVersion).map(v => (
101-
<option key={v} value={v}>
102-
{v}
103-
</option>
104-
))}
105-
</select>
106-
</div>
107-
) : null}
108-
</div>
109-
</ConfirmModal>
110-
);
92+
To version:
93+
</label>
94+
<select
95+
name="asyncapi-version"
96+
className="shadow-sm focus:ring-pink-500 focus:border-pink-500 w-1/2 block w-full sm:text-sm border-gray-300 rounded-md py-2 px-1 text-gray-700 border-pink-300 border-2"
97+
onChange={e => setVersion(e.target.value)}
98+
value={version}
99+
>
100+
<option value={latestVersion} key={latestVersion}>{latestVersion} (latest)</option>
101+
{reservedAllowedVersions.filter((v) => v !== latestVersion).map(v => (
102+
<option key={v} value={v}>
103+
{v}
104+
</option>
105+
))}
106+
</select>
107+
</div>
108+
) : null}
109+
</div>
110+
</ConfirmModal>
111+
);
112+
}
111113
});

apps/studio/src/services/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ import { ServerAPIService } from './server-api.service';
1313
import { SettingsService } from './settings.service';
1414
import { SocketClient } from './socket-client.service';
1515
import { SpecificationService } from './specification.service';
16+
import { PreviewSockeClient } from './preview.service';
1617

1718
export type Services = {
1819
appSvc: ApplicationService;
20+
previewSvc: PreviewSockeClient;
1921
converterSvc: ConverterService;
2022
editorSvc: EditorService;
2123
formatSvc: FormatService;
@@ -41,6 +43,7 @@ export async function createServices() {
4143

4244
services.parserSvc = new ParserService(services);
4345
services.appSvc = new ApplicationService(services);
46+
services.previewSvc = new PreviewSockeClient(services);
4447
services.converterSvc = new ConverterService(services);
4548
services.editorSvc = new EditorService(services);
4649
services.formatSvc = new FormatService(services);

apps/studio/src/services/navigation.service.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export class NavigationService extends AbstractService {
2020
share: urlParams.get('share'),
2121
readOnly: urlParams.get('readOnly') === 'true' || urlParams.get('readOnly') === '',
2222
liveServer: urlParams.get('liveServer'),
23+
previewServer: urlParams.get('previewServer'),
2324
redirectedFrom: urlParams.get('redirectedFrom'),
2425
};
2526
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { appState } from '@/state';
2+
import { AbstractService } from './abstract.service';
3+
import toast from 'react-hot-toast';
4+
5+
interface IncomingMessage {
6+
type: 'preview:file:added' | 'preview:file:changed' | 'preview:file:deleted' | 'preview:connected';
7+
code?: string
8+
}
9+
10+
export class PreviewSockeClient extends AbstractService {
11+
private ws: WebSocket | null = null;
12+
private isVerified = false;
13+
14+
public override onInit(): void {
15+
// return if the readOnly state is already set by the application service by presence of url and readOnly parameter
16+
if (appState.getState().readOnly) {
17+
return
18+
}
19+
this.disconnect();
20+
const {previewServer} = this.svcs.navigationSvc.getUrlParameters();
21+
22+
const previewServerPort = previewServer && Number(previewServer);
23+
24+
if (previewServer && previewServerPort) {
25+
try {
26+
this.ws = new WebSocket(`ws://${'localhost'}:${previewServerPort}/preview-server`);
27+
this.ws.onopen = this.onOpen.bind(this);
28+
this.ws.onerror = this.onError.bind(this);
29+
this.ws.onmessage = this.handleMessage.bind(this);
30+
} catch (e) {
31+
console.log(e)
32+
this.onError();
33+
}
34+
}
35+
}
36+
37+
private handleMessage(event: MessageEvent<any>) {
38+
try {
39+
const message: IncomingMessage = JSON.parse(event.data);
40+
if (!this.isVerified) {
41+
if (message.type === 'preview:connected') {
42+
this.isVerified = true;
43+
appState.setState({
44+
readOnly: true,
45+
initialized: true,
46+
});
47+
return;
48+
}
49+
console.error('Received unexpected message before verification:', message);
50+
this.disconnect();
51+
return;
52+
}
53+
// after verification handling rest of the messages
54+
switch (message.type) {
55+
case 'preview:file:added':
56+
case 'preview:file:changed':
57+
this.svcs.editorSvc.updateState({
58+
content: message.code as string,
59+
updateModel: true,
60+
sendToServer: false,
61+
});
62+
break;
63+
case 'preview:file:deleted':
64+
console.warn('Preview Server: The file has been deleted on the file system.');
65+
break;
66+
default:
67+
console.warn('Live Server: An unknown even has been received. See details in console');
68+
console.error(message);
69+
break;
70+
}
71+
} catch (error) {
72+
console.log(error)
73+
}
74+
}
75+
disconnect() {
76+
if (this.ws) {
77+
this.ws.close();
78+
this.ws = null;
79+
}
80+
this.isVerified =false;
81+
}
82+
83+
private onOpen() {
84+
toast.success(
85+
<div>
86+
<span className="block text-bold">
87+
Correctly connected to the preview server!
88+
</span>
89+
</div>
90+
);
91+
appState.setState({ liveServer: true });
92+
}
93+
94+
private onError() {
95+
toast.error(
96+
<div>
97+
<span className="block text-bold">
98+
Failed to connect to preview server. Please check developer console for more information.
99+
</span>
100+
</div>
101+
);
102+
appState.setState({ liveServer: false });
103+
}
104+
}

apps/studio/src/services/socket-client.service.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ export class SocketClient extends AbstractService {
1313
private ws!: WebSocket;
1414

1515
public override onInit(): void {
16-
const { url, base64, readOnly, liveServer } = this.svcs.navigationSvc.getUrlParameters();
16+
const { url, base64, readOnly, liveServer, previewServer } = this.svcs.navigationSvc.getUrlParameters();
1717

18-
const shouldConnect = !(base64 || url || readOnly);
18+
const shouldConnect = !(base64 || url || readOnly || previewServer);
1919
if (!shouldConnect) {
2020
return;
2121
}

0 commit comments

Comments
 (0)