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

Integrate APIs to AI Onboarding #370

Merged
merged 9 commits into from
Nov 28, 2023
Merged
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
1 change: 1 addition & 0 deletions includes/RestApi/RestApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ final class RestApi {
'NewfoldLabs\WP\\Module\\Onboarding\\RestApi\\Themes\\ThemeFontsController',
'NewfoldLabs\WP\\Module\\Onboarding\\RestApi\\Themes\\ThemeColorsController',
'NewfoldLabs\\WP\\Module\\Onboarding\\RestApi\\SiteClassificationController',
'NewfoldLabs\\WP\\Module\\Onboarding\\RestApi\\SiteGenController',
);

/**
Expand Down
109 changes: 109 additions & 0 deletions includes/RestApi/SiteGenController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php

namespace NewfoldLabs\WP\Module\Onboarding\RestApi;

use NewfoldLabs\WP\Module\Onboarding\Permissions;
use NewfoldLabs\WP\Module\Onboarding\Data\Services\SiteGenService;

/**
* Class SiteGenController
*/
class SiteGenController {

/**
* The namespace of this controller's route.
*
* @var string
*/
protected $namespace = 'newfold-onboarding/v1';

/**
* The endpoint base
*
* @var string
*/
protected $rest_base = '/sitegen';

/**
* Registers rest routes for SiteGenController class.
*
* @return void
*/
public function register_routes() {
\register_rest_route(
$this->namespace,
$this->rest_base . '/get-identifiers',
array(
'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get_valid_identifiers' ),
'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ),
)
);
\register_rest_route(
$this->namespace,
$this->rest_base . '/generate',
array(
'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'generate_sitegen_meta' ),
'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ),
'args' => $this->sitegen_meta_args(),
)
);
}

/**
* Required Args for Generating Site Gen Meta.
*
* @return array
*/
public function sitegen_meta_args() {
return array(
'site_info' => array(
'required' => true,
'type' => 'object',
),
'identifier' => array(
'required' => true,
'type' => 'string',
),
'skip_cache' => array(
'required' => false,
'type' => 'boolean',
),
);
}

/**
* Gets all the valid Identifiers
*
* @return array
*/
public function get_valid_identifiers() {
return array_keys( array_filter( SiteGenService::get_identifiers() ) );
}

/**
* Generate Sitegen meta data.
*
* @param \WP_REST_Request $request Request model.
*
* @return array|WP_Error
*/
public function generate_sitegen_meta( \WP_REST_Request $request ) {

$site_info = $request->get_param( 'site_info' );
$identifier = $request->get_param( 'identifier' );
$skip_cache = $request->get_param( 'skip_cache' );

if ( SiteGenService::is_enabled() ) {
// TODO Implement the main function and do computations if required.
return SiteGenService::instantiate_site_meta( $site_info, $identifier, $skip_cache );
}

return new \WP_Error(
'sitegen-error',
'SiteGen is Disabled.',
array( 'status' => 404 )
);
}
}
11 changes: 10 additions & 1 deletion src/OnboardingSPA/components/Button/NextButtonSiteGen/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import { Button } from '@wordpress/components';
import { Icon, chevronRight } from '@wordpress/icons';
import { store as nfdOnboardingStore } from '../../../store';

const NextButtonSiteGen = ( { text, className, callback = null } ) => {
const NextButtonSiteGen = ( {
text,
className,
callback = null,
disabled = false,
} ) => {
const navigate = useNavigate();
const { nextStep } = useSelect( ( select ) => {
return {
Expand All @@ -16,9 +21,13 @@ const NextButtonSiteGen = ( { text, className, callback = null } ) => {
<Button
className={ classNames(
'nfd-onboarding-button--site-gen-next',
{ 'nfd-onboarding-button--site-gen-next--disabled': disabled },
className
) }
onClick={ () => {
if ( disabled ) {
return;
}
if ( callback && typeof callback === 'function' ) {
callback();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@
height: 30px;
margin-top: 10px;
}

&--disabled {
background-color: rgba(var(--nfd-onboarding-primary-rgb), 0.4);

&:hover {
cursor: not-allowed;
color: var(--nfd-onboarding-secondary);
}
}
}

&--icon {
Expand Down
18 changes: 11 additions & 7 deletions src/OnboardingSPA/components/Loaders/SiteGenLoader/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,16 @@ const SiteGenLoader = ( { autoNavigate = false } ) => {
const [ percentage, setPercentage ] = useState( 0 );
const [ status, setStatus ] = useState( content.status[ statusIdx ].title );

const { nextStep } = useSelect( ( select ) => {
const { currentData, nextStep } = useSelect( ( select ) => {
return {
currentData:
select( nfdOnboardingStore ).getCurrentOnboardingData(),
nextStep: select( nfdOnboardingStore ).getNextStep(),
};
} );

const checkStatus = async () => {
// Make fake API Call to get the status.
if ( percentage !== 100 ) setPercentage( ( t ) => t + 10 );
};

useEffect( () => {
const statusTimer = setInterval( () => {
checkStatus();
statusIdx += 1;
if ( statusIdx === content.status.length ) statusIdx = 0;
setStatus( content.status[ statusIdx ].title );
Expand All @@ -34,6 +30,14 @@ const SiteGenLoader = ( { autoNavigate = false } ) => {
};
}, [] );

useEffect( () => {
const percentageValue =
( currentData.sitegen.siteGenMetaStatus.currentStatus /
currentData.sitegen.siteGenMetaStatus.totalCount ) *
100;
setPercentage( percentageValue );
}, [ currentData.sitegen.siteGenMetaStatus.currentStatus ] );

useEffect( () => {
if ( percentage === 100 ) {
if ( nextStep && autoNavigate ) {
Expand Down
103 changes: 101 additions & 2 deletions src/OnboardingSPA/components/NewfoldInterfaceSkeleton/SiteGen/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import NewfoldInterfaceSkeleton from '../index';
import { useEffect } from '@wordpress/element';
import { useLocation } from 'react-router-dom';
import { useSelect, useDispatch } from '@wordpress/data';

import Header from '../../Header';
import Content from '../../Content';
import Sidebar from '../../Sidebar';
import themeToggleHOC from '../themeToggleHOC';
import NewfoldInterfaceSkeleton from '../index';
import ToggleDarkMode from '../../ToggleDarkMode';
import { ThemeProvider } from '../../ThemeContextProvider';
import themeToggleHOC from '../themeToggleHOC';
import { store as nfdOnboardingStore } from '../../../store';
import { setFlow } from '../../../utils/api/flow';
import {
generateSiteGenMeta,
getSiteGenIdentifiers,
} from '../../../utils/api/siteGen';

// Wrapping the NewfoldInterfaceSkeleton with the HOC to make theme available
const ThemedNewfoldInterfaceSkeleton = themeToggleHOC(
Expand All @@ -14,6 +24,95 @@ const ThemedNewfoldInterfaceSkeleton = themeToggleHOC(
);

const SiteGen = () => {
const location = useLocation();

const { currentData } = useSelect( ( select ) => {
return {
currentData:
select( nfdOnboardingStore ).getCurrentOnboardingData(),
};
} );

const { setCurrentOnboardingData } = useDispatch( nfdOnboardingStore );

async function syncStoreToDB() {
if ( currentData ) {
//Set the Flow Data and sync store and DB
setFlow( currentData );
}
}

async function generateSiteGenData() {
// Start the API Requests when the loader is shown.
if (
! (
location.pathname.includes( 'experience' ) ||
location.pathname.includes( 'building' )
)
) {
return;
}

// If the calls are already made then skip doing that again.
if (
currentData.sitegen.siteGenMetaStatus.currentStatus >=
currentData.sitegen.siteGenMetaStatus.totalCount
) {
return;
}

let identifiers = await getSiteGenIdentifiers();
identifiers = identifiers.body;

const midIndex = Math.floor( identifiers.length / 2 );
if ( location.pathname.includes( 'experience' ) ) {
identifiers = identifiers.slice( 0, midIndex );
} else if ( location.pathname.includes( 'building' ) ) {
identifiers = identifiers.slice( midIndex );
}

const siteInfo = {
site_description: currentData.sitegen?.siteDetails?.prompt,
};

// Iterate over Identifiers and fire Requests!
identifiers.forEach( ( identifier ) => {
return new Promise( () =>
generateSiteGenMeta( siteInfo, identifier )
.then( ( data ) => {
if ( data.body !== null ) {
currentData.sitegen.siteGenMetaStatus.currentStatus += 1;
setCurrentOnboardingData( currentData );
}
} )
/* eslint-disable no-console */
.catch( ( err ) => console.log( err ) )
);
} );
}

const handlePreviousStepTracking = () => {
const previousStep = window.nfdOnboarding?.previousStep;
if ( typeof previousStep !== 'object' ) {
window.nfdOnboarding.previousStep = {
path: location.pathname,
url: window.location.href,
};
return;
}

window.nfdOnboarding.previousStep = {
path: location.pathname,
url: window.location.href,
};
};

useEffect( () => {
syncStoreToDB();
generateSiteGenData();
handlePreviousStepTracking();
}, [ location.pathname ] );

return (
<ThemeProvider>
<ThemedNewfoldInterfaceSkeleton
Expand Down
4 changes: 4 additions & 0 deletions src/OnboardingSPA/steps/SiteGen/SiteDetails/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ const SiteGenSiteDetails = () => {
className={ 'nfd-sg-site-details--next-btn' }
text={ content.buttonText }
callback={ checkAndNavigate }
disabled={
customerInput === undefined ||
customerInput === ''
}
/>
</div>
</div>
Expand Down
30 changes: 30 additions & 0 deletions src/OnboardingSPA/utils/api/siteGen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import apiFetch from '@wordpress/api-fetch';

import { resolve } from './resolve.js';
import { onboardingRestURL } from './common';

export async function getSiteGenIdentifiers() {
return await resolve(
apiFetch( {
url: onboardingRestURL( 'sitegen/get-identifiers' ),
} ).then()
);
}

export async function generateSiteGenMeta(
siteInfo,
identifier,
skipCache = false
) {
return await resolve(
apiFetch( {
url: onboardingRestURL( 'sitegen/generate' ),
method: 'POST',
data: {
site_info: siteInfo,
identifier,
skip_cache: skipCache,
},
} ).then()
);
}