Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Comments for methods, classes and interface. #254

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions react/src/AuthGate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,39 @@ import React, {Component} from 'react';

import {SDK} from '@ringcentral/sdk';

// Utility function to get display name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is a display name? Who's name? A user? A service? Or something else

function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}

// Utility function for delaying execution
const delay = () => new Promise(res => setTimeout(res, 0));

// Interface for the state of AuthGate component
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need param description

export interface AuthGateState {
isAuthorized: boolean;
authorizing: boolean;
authError: null | Error;
}

// Interface for the render props provided by AuthGate
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need param description

export interface AuthGateRenderProps extends AuthGateState {
loginUrl: (options: any) => string;
parseRedirect: (search: string) => Promise<any>;
logout: () => Promise<any>;
}

// Interface for the props of AuthGate component
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need param description

export interface AuthGateProps {
sdk: SDK;
ensure?: boolean;
children: (props: AuthGateRenderProps) => any;
}

// AuthGate component definition
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does AuthGate do in general?

export class AuthGate extends Component<AuthGateProps, AuthGateState> {

// Initial state
public state = {
isAuthorized: false,
authorizing: true,
Expand All @@ -51,6 +59,7 @@ export class AuthGate extends Component<AuthGateProps, AuthGateState> {
const {sdk, ensure} = this.props;
const platform = sdk.platform();

// Event listeners for various platform events
platform.on(platform.events.beforeRefresh, this.before);
platform.on(platform.events.beforeLogin, this.before);
platform.on(platform.events.refreshError, this.error);
Expand All @@ -73,6 +82,7 @@ export class AuthGate extends Component<AuthGateProps, AuthGateState> {
this.mounted = false;
const {sdk} = this.props;
const platform = sdk.platform();
// Removing event listeners
platform.removeListener(platform.events.beforeRefresh, this.before);
platform.removeListener(platform.events.beforeLogin, this.before);
platform.removeListener(platform.events.refreshError, this.error);
Expand All @@ -82,19 +92,25 @@ export class AuthGate extends Component<AuthGateProps, AuthGateState> {
platform.removeListener(platform.events.refreshSuccess, this.success);
}

// Handler for before event
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do in the handler?

public before = () => this.mounted && this.setState({authorizing: true});

// Handler for error event
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do in the handler?

public error = async e => this.updateState(e);

// Handler for success event
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do in the handler?

public success = async () => this.updateState(null);

// Method to get login URL
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's in options?

public loginUrl = options => this.props.sdk.platform().loginUrl(options);

// Method to logout
public logout = async () => {
const platform = this.props.sdk.platform();
return platform.logout();
};

// Method to parse redirect
public parseRedirect = async search => {
try {
const platform = this.props.sdk.platform();
Expand All @@ -107,6 +123,7 @@ export class AuthGate extends Component<AuthGateProps, AuthGateState> {
}
};

// Method to update state
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need more description of this method. This looks a bit like an unauth, which is confusing. Why is authorizing set to false?

public updateState = async (authError = null) => {
await delay();
this.mounted &&
Expand All @@ -120,6 +137,7 @@ export class AuthGate extends Component<AuthGateProps, AuthGateState> {
});
};

// Render method
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not this one, but the one below if you expand the hidden code for Line 153 ~162.

There's a clear comment saying TODO Definition there. That's a very clear sign that we want to add its definition there.

public render() {
const {sdk, ensure, children, ...props} = this.props;
return children({
Expand Down
7 changes: 7 additions & 0 deletions redux-demo/src/pages/Index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,20 @@ class Index extends Component<any, IndexState> {
}
}

/**
* Renders the component based on the current state.
* @returns JSX representing the rendered component.
*/
public render() {
const {error, user} = this.state;

// If there's an error, render an error message.
if (error) {return <div>Error: {error.toString()}</div>;}

// If user data is not available yet, render a loading message.
if (!user) {return <div>Loading...</div>;}

// If user data is available, render user information and a logout button.
return (
<div>
<h1>Logged in as {user.name}</h1>
Expand Down
39 changes: 35 additions & 4 deletions redux/src/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,66 @@ import {AUTH_ERROR, LOGIN, LOGIN_SUCCESS, LOGOUT, LOGOUT_SUCCESS} from './consta
export interface ActionsOptions {
sdk: SDK;
}

/**
* Actions class responsible for handling authentication actions
*/
export default class Actions {
public sdk: SDK;

// Constructor to initialize the Actions class with an SDK instance
public constructor({sdk}: ActionsOptions) {
this.sdk = sdk;
}

public login = query => {
if (query.error_description) {return this.authError(new Error(query.error_description));}
/**
* Method to handle login action
* It initiates the login process using the SDK
* If an error description is provided, it dispatches an authentication error
* Returns an action of type LOGIN
* @param query
* @returns
*/
public login = (query) => {
if (query.error_description) {
return this.authError(new Error(query.error_description));
}
this.sdk.login(query); // we ignore promise result because we listen to all events already
return {type: LOGIN};
};

/**
* Method to handle logout action
* It initiates the logout process using the SDK
* @returns Returns an action of type LOGOUT
*/
public logout = () => {
this.sdk.logout(); // we ignore promise result because we listen to all events already
return {type: LOGOUT};
};

/**
* Method to dispatch login success action
* @returns Returns an action of type LOGIN_SUCCESS
*/
public loginSuccess = () => ({
type: LOGIN_SUCCESS,
});

public authError = error => ({
/**
* Method to dispatch authentication error action
* @param error Takes an error object as input and dispatches an action of type AUTH_ERROR
* @returns Returns the dispatched action
*/
public authError = (error) => ({
type: AUTH_ERROR,
payload: error,
error: true,
});

/**
* Method to dispatch logout success action
* @returns Returns an action of type LOGOUT_SUCCESS
*/
public logoutSuccess = () => ({
type: LOGOUT_SUCCESS,
});
Expand Down
45 changes: 33 additions & 12 deletions redux/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,55 +8,76 @@ export interface StoreConnectorOptions extends ActionsOptions {
root?: string;
}

/**
* Class responsible for connecting authentication actions with Redux store
*/
export default class StoreConnector {
private sdk: SDK;
private sdk: SDK; // SDK instance for authentication

private store: Store;
private store: Store; // Redux store to connect with

public root: string;
public root: string; // Root key in the Redux store for authentication state

public actions: Actions;
public actions: Actions; // Instance of Actions class for dispatching authentication actions

/**
* Constructor to initialize StoreConnector with SDK instance and options
*/
public constructor({sdk, root = 'rcAuth'}: StoreConnectorOptions) {
this.sdk = sdk;
this.root = root;
this.actions = new Actions({sdk});
}

/**
* Method to connect StoreConnector with a Redux store
* Attaches event listeners to SDK platform events for handling authentication
* Dispatches actions based on authentication events
*/
public connectToStore = async (store: Store) => {
this.store = store;
const {dispatch} = store;
const platform = this.sdk.platform();

platform.on(platform.events.loginError, e => dispatch(this.actions.authError(e)));
platform.on(platform.events.refreshError, e => dispatch(this.actions.authError(e)));
platform.on(platform.events.logoutError, e => dispatch(this.actions.authError(e)));
// Event listeners for handling authentication events
platform.on(platform.events.loginError, (e) => dispatch(this.actions.authError(e)));
platform.on(platform.events.refreshError, (e) => dispatch(this.actions.authError(e)));
platform.on(platform.events.logoutError, (e) => dispatch(this.actions.authError(e)));

platform.on(platform.events.loginSuccess, () => dispatch(this.actions.loginSuccess()));
platform.on(platform.events.logoutSuccess, () => dispatch(this.actions.logoutSuccess()));

try {
// Checking if access token is valid or refreshing token
if (await platform.auth().accessTokenValid()) {
dispatch(this.actions.loginSuccess()); // manual dispatch
} else {
await platform.refresh();
}
} catch (e) { //eslint-disable-line
} catch (e) {
//eslint-disable-line
// can be empty because error is caught by event listener
}
};

/**
* Reducer function for combining authentication reducers
*/
public reducer = combineReducers({
status,
error,
loading,
});

public getAuth = state => state[this.root];
// Selector function to get authentication state from Redux store
public getAuth = (state) => state[this.root];

public getAuthStatus = state => this.getAuth(state).status;
// Selector function to get authentication status from Redux store
public getAuthStatus = (state) => this.getAuth(state).status;

public getAuthError = state => this.getAuth(state).error;
// Selector function to get authentication error from Redux store
public getAuthError = (state) => this.getAuth(state).error;

public getAuthLoading = state => this.getAuth(state).loading;
// Selector function to get authentication loading state from Redux store
public getAuthLoading = (state) => this.getAuth(state).loading;
}
29 changes: 29 additions & 0 deletions sdk/src/SDK.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,39 +44,68 @@ export class SDK {

public static EventEmitter = EventEmitter;

/**
* Sandbox Server https://platform.devtest.ringcentral.com
* Production Server https://platform.ringcentral.com
*/
public static server = {
sandbox: 'https://platform.devtest.ringcentral.com',
production: 'https://platform.ringcentral.com',
};

/**
* Handles login redirect by sending authentication response to the opener window.
* @param origin The origin to post the message to.
* @param win The window object. If not provided, defaults to the global window object.
*/
public static handleLoginRedirect(origin, win) {
// Use the provided window object or default to the global window object.
win = win || window;

// Get the authentication response from the location search or hash.
const response = win.location.search ? win.location.search : win.location.hash;

// Create a message object containing the authentication response.
const msg = {};
msg[Constants.authResponseProperty] = response;

// Post the message to the opener window with the specified origin.
win.opener.postMessage(msg, origin || win.location.origin);
}

/**
* Constructs a new SDK instance with the provided options.
* @param options The SDK options.
*/
public constructor(options: SDKOptions = {}) {
// Destructure options or use default values.
const {cachePrefix, defaultRequestInit, handleRateLimit} = options;

// Warn if using sandbox server (deprecated).
if (options?.server === SDK.server.sandbox) {
// eslint-disable-next-line no-console
console.warn('Sandbox support is deprecated. Please migrate your application to Production Server.');
}

// Initialize external dependencies.
this._externals = new Externals({
...defaultExternals,
...options,
});

// Initialize cache.
this._cache = new Cache({
externals: this._externals,
prefix: cachePrefix,
});

// Initialize client.
this._client = new Client({
externals: this._externals,
defaultRequestInit,
});

// Initialize platform.
this._platform = new Platform({
...options,
externals: this._externals,
Expand Down
Loading