Skip to content

Commit

Permalink
feat: support URL parameters (#113)
Browse files Browse the repository at this point in the history
Co-authored-by: Jonas Lagoni <[email protected]>
  • Loading branch information
magicmatatjahu and jonaslagoni authored Oct 7, 2021
1 parent d4d7fc2 commit 86fa4ea
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 7 deletions.
2 changes: 1 addition & 1 deletion src/components/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import React, { useEffect, useState } from 'react';

import { AsyncAPIDocument } from '@asyncapi/parser';

import state from '../state';
import { NavigationService } from '../services';
import state from '../state';

interface NavigationProps {}

Expand Down
22 changes: 18 additions & 4 deletions src/components/Template/HTMLWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react';
import React, { useEffect } from 'react';
import { AsyncAPIDocument } from '@asyncapi/parser';
import { AsyncApiComponentWP } from '@asyncapi/react-component';

import { NavigationService } from '../../services';
import state from '../../state';

interface HTMLWrapperProps {}
Expand All @@ -10,13 +11,21 @@ export const HTMLWrapper: React.FunctionComponent<HTMLWrapperProps> = () => {
const parserState = state.useParserState();
const editorState = state.useEditorState();

// using "json()"" for removing proxy from value
const editorLoaded = editorState.editorLoaded.get();

// using "json()" for removing proxy from value
let parsedSpec = parserState.parsedSpec.value;
parsedSpec = parsedSpec
? new (AsyncAPIDocument as any)(parsedSpec.json())
: null;

if (editorState.editorLoaded.get() === false) {
useEffect(() => {
if (editorLoaded === true) {
setTimeout(NavigationService.scrollToHash, 0);
}
}, [editorLoaded]); // eslint-disable-line

if (editorLoaded === false) {
return (
<div className="flex flex-1 overflow-hidden h-full justify-center items-center text-2xl mx-auto px-6 text-center">
Loading...
Expand All @@ -38,7 +47,12 @@ export const HTMLWrapper: React.FunctionComponent<HTMLWrapperProps> = () => {
<div className="overflow-auto">
<AsyncApiComponentWP
schema={parsedSpec}
config={{ show: { errors: false } }}
config={{
show: {
sidebar: NavigationService.isReadOnly(true),
errors: false,
},
}}
/>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export * from './Editor';
export * from './Content';
export * from './Navigation';
export * from './Sidebar';
export * from './Template';
export * from './Toolbar';
45 changes: 45 additions & 0 deletions src/services/navigation.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// @ts-ignore
import { getLocationOf } from '@asyncapi/parser/lib/utils';

import { EditorService } from './editor.service';
import { SpecificationService } from './specification.service';
import state from '../state';

interface LocationOf {
jsonPointer: string;
startLine: number;
Expand Down Expand Up @@ -59,6 +63,47 @@ export class NavigationService {
}
}

static isReadOnly(strict = false) {
const urlParams = new URLSearchParams(window.location.search);
const isReadonly = urlParams.get('readOnly') === 'true' || urlParams.get('readOnly') === ''
? true
: false;

if (strict === false) {
return isReadonly;
}
return isReadonly && !!(urlParams.get('url') || urlParams.get('load') || urlParams.get('base64'));
}

static async onInitApp() {
const urlParams = new URLSearchParams(window.location.search);

const documentUrl = urlParams.get('url') || urlParams.get('load');
const base64Document = urlParams.get('base64');

if (!documentUrl && !base64Document) {
state.app.initialized.set(true);
return;
}

if (documentUrl) {
await EditorService.importFromURL(documentUrl);
} else if (base64Document) {
await EditorService.importBase64(base64Document);
}

if (this.isReadOnly()) {
await SpecificationService.parseSpec(state.editor.editorValue.get());
state.sidebar.show.set(false);
state.editor.set({
...state.editor.get(),
monacoLoaded: true,
editorLoaded: true,
});
}
state.app.initialized.set(true);
}

private static emitHashChangeEvent(hash: string) {
hash = hash.startsWith('#') ? hash : `#${hash}`;
window.history.pushState({}, '', hash);
Expand Down
64 changes: 64 additions & 0 deletions src/services/tests/navigation.service.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { NavigationService } from '../navigation.service';

describe('NavigationService', () => {
function updateLocation(search: string) {
const location = {
...window.location,
search,
};
Object.defineProperty(window, 'location', {
writable: true,
value: location,
});
}

describe('.isReadOnly', () => {
test('should return false if reaOnly flag is not defined', () => {
updateLocation('?url=some-url.json');
const result = NavigationService.isReadOnly();
expect(result).toEqual(false);
});

test('should return true if reaOnly flag is defined - empty value case', () => {
updateLocation('?readOnly');
const result = NavigationService.isReadOnly();
expect(result).toEqual(true);
});

test('should return true if reaOnly flag is defined - true value case', () => {
updateLocation('?readOnly=true');
const result = NavigationService.isReadOnly();
expect(result).toEqual(true);
});

test('should return false if reaOnly flag is not defined - non empty/true value case', () => {
updateLocation('?readOnly=false');
const result = NavigationService.isReadOnly();
expect(result).toEqual(false);
});

test('should return false if reaOnly flag is not defined - strict mode case without other parameters', () => {
updateLocation('?readOnly=true');
const result = NavigationService.isReadOnly(true);
expect(result).toEqual(false);
});

test('should return true if reaOnly flag is not defined - strict mode case with url parameter', () => {
updateLocation('?readOnly=true&url=some-url.json');
const result = NavigationService.isReadOnly(true);
expect(result).toEqual(true);
});

test('should return true if reaOnly flag is not defined - strict mode case with load parameter', () => {
updateLocation('?readOnly=true&load=some-url.json');
const result = NavigationService.isReadOnly(true);
expect(result).toEqual(true);
});

test('should return true if reaOnly flag is not defined - strict mode case with base64 parameter', () => {
updateLocation('?readOnly=true&base64=AsyncAPI');
const result = NavigationService.isReadOnly(true);
expect(result).toEqual(true);
});
});
});
17 changes: 15 additions & 2 deletions src/studio.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
import React from 'react';
import React, { useEffect } from 'react';
import { Toaster } from 'react-hot-toast';

import { Content, Sidebar, Toolbar } from './components';
import { Content, Sidebar, Template, Toolbar } from './components';
import { ConvertToLatestModal } from './components/Modals';
import { NavigationService } from './services';

export interface AsyncAPIStudioProps {}

const AsyncAPIStudio: React.FunctionComponent<AsyncAPIStudioProps> = () => {
useEffect(() => {
NavigationService.onInitApp();
}, []);

if (NavigationService.isReadOnly(true)) {
return (
<div className="flex flex-row flex-1 overflow-hidden h-full w-full h-screen">
<Template />
</div>
);
}

return (
<div className="flex flex-col h-full w-full h-screen">
<Toolbar />
Expand Down

0 comments on commit 86fa4ea

Please sign in to comment.