Skip to content

Commit

Permalink
added install instructions for self managed extensions and package lo…
Browse files Browse the repository at this point in the history
…okup endpoint
  • Loading branch information
roncodes committed Aug 5, 2024
1 parent 8b715af commit d6fc843
Show file tree
Hide file tree
Showing 10 changed files with 213 additions and 1 deletion.
22 changes: 22 additions & 0 deletions addon/components/extension-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,18 @@ export default class ExtensionCardComponent extends Component {
stepDescription: 'Awaiting install to begin...',
progress: 0,
extension: this.extension,
viewSelfManagesInstallInstructions: () => {
const done = async () => {
await this.modalsManager.done();
this.onClick();
};

this.selfManagedInstallInstructions({
extension: this.extension,
confirm: done,
decline: done,
});
},
confirm: async (modal) => {
modal.startLoading();

Expand Down Expand Up @@ -122,6 +134,16 @@ export default class ExtensionCardComponent extends Component {
});
}

async selfManagedInstallInstructions(options = {}) {
await this.modalsManager.done();
this.modalsManager.show('modals/self-managed-install-instructions', {
title: 'Install a Self Managed Extension',
hideDeclineButton: true,
acceptButtonText: 'Done',
...options,
});
}

async startCheckoutSession() {
const checkout = await this.stripe.initEmbeddedCheckout({
fetchClientSecret: this.fetchClientSecret.bind(this),
Expand Down
22 changes: 22 additions & 0 deletions addon/components/extension-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,30 @@ export default class ExtensionFormComponent extends Component {
acceptButtonDisabled: true,
acceptButtonScheme: isPaymentRequired ? 'success' : 'primary',
declineButtonText: 'Done',
viewSelfManagesInstallInstructions: () => {
const done = async () => {
await this.modalsManager.done();
this.previewListing();
};

this.selfManagedInstallInstructions({
extension,
confirm: done,
decline: done,
});
},
extension,
...options,
});
}

async selfManagedInstallInstructions(options = {}) {
await this.modalsManager.done();
this.modalsManager.show('modals/self-managed-install-instructions', {
title: 'Install a Self Managed Extension',
hideDeclineButton: true,
acceptButtonText: 'Done',
...options,
});
}
}
3 changes: 3 additions & 0 deletions addon/components/modals/extension-details.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@
<Badge @status="info" @hideStatusDot={{true}} @helpText={{t "registry-bridge.component.extension-details-modal.self-managed-help-text"}}>{{t
"registry-bridge.component.extension-details-modal.self-managed"
}}</Badge>
{{#if @options.viewSelfManagesInstallInstructions}}
<a href="#" class="text-xs text-blue-400 hover:opacity-50" {{on "click" @options.viewSelfManagesInstallInstructions}}><FaIcon @icon="circle-info" class="mr-1" />How to install</a>
{{/if}}
</div>
{{/if}}
</div>
Expand Down
29 changes: 29 additions & 0 deletions addon/components/modals/self-managed-install-instructions.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<Modal::Default @modalIsOpened={{@modalIsOpened}} @options={{@options}} @confirm={{@onConfirm}} @decline={{@onDecline}}>
<div class="modal-body-container">
<ol class="self-managed-install-instructions">
<li>
<div class="flex">
<LinkTo @route="console.extensions.developers.credentials" class="text-blue-500 hover:opacity-50">Generate a Fleetbase registry credentials token.</LinkTo>
</div>
</li>
<li>
<div class="flex">Install fleetbase-cli
<ClickToCopy @value={{concat "npm i -g @fleetbase/cli"}}><code>npm i -g @fleetbase/cli</code></ClickToCopy>
</div>
</li>
<li>
<div class="flex">Run
<ClickToCopy @value={{concat "flb set-auth"}}><code>flb set-auth {YOUR_TOKEN}</code></ClickToCopy>
</div>
</li>
<li>
<div class="flex">
Run install
<ClickToCopy @value={{concat "flb install fleetbase/" @options.extension.slug}}><code>flb install fleetbase/{{@options.extension.slug}}</code></ClickToCopy>
or
<ClickToCopy @value={{concat "flb install " @options.extension.public_id}}><code>flb install {{@options.extension.public_id}}</code></ClickToCopy>
</div>
</li>
</ol>
</div>
</Modal::Default>
28 changes: 28 additions & 0 deletions addon/styles/registry-bridge-engine.css
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,31 @@ body[data-theme='dark'] .extension-card-container > .extension-card-body-contain
margin-left: 2rem;
margin-bottom: 2rem;
}

.self-managed-install-instructions {
list-style: decimal;
color: #000;
padding-left: 30px;
font-size: 1rem;
}

.self-managed-install-instructions > li {
padding-bottom: 0.5rem;
}

body[data-theme='dark'] .self-managed-install-instructions {
list-style: decimal;
color: #fff;
padding-left: 30px;
}

.self-managed-install-instructions code {
font-family: monospace;
padding: 0.05rem 0.2rem;
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 5%);
background-color: #030712;
border: 1px #1f2937 solid;
color: #22c55e;
border-radius: 0.25rem;
font-size: 0.75rem;
}
1 change: 1 addition & 0 deletions app/components/modals/self-managed-install-instructions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from '@fleetbase/registry-bridge-engine/components/modals/self-managed-install-instructions';
46 changes: 46 additions & 0 deletions server/src/Http/Controllers/Internal/v1/RegistryController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Fleetbase\Http\Resources\Category as CategoryResource;
use Fleetbase\Models\Category;
use Fleetbase\RegistryBridge\Models\RegistryExtension;
use Illuminate\Http\Request;

class RegistryController extends Controller
{
Expand Down Expand Up @@ -51,4 +52,49 @@ public function getInstalledEngines()

return response()->json($installedExtensions);
}

/**
* Lookup and retrieve package information based on the provided package name.
*
* This method handles a request to lookup a package by its name. It utilizes the `RegistryExtension::lookup` method to find the
* corresponding registry extension. If no extension is found or if the extension does not have valid package or composer data,
* an error response is returned.
*
* If a valid extension and its associated bundle are found, the function extracts the package and composer names from the
* `package.json` and `composer.json` metadata. These names are then returned in a JSON response.
*
* @param Request $request the incoming HTTP request containing the 'package' input parameter
*
* @return \Illuminate\Http\JsonResponse a JSON response containing the package and composer names if found, or an error message otherwise
*/
public function lookupPackage(Request $request)
{
$packageName = $request->input('package');
$registryExtension = RegistryExtension::lookup($packageName);
if (!$registryExtension) {
return response()->error('No extension found by this name for install');
}

if (!$registryExtension->currentBundle) {
return response()->error('No valid package data found for this extension install');
}

$packageJson = $registryExtension->currentBundle->meta['package.json'];
if (!$packageJson) {
return response()->error('No valid package data found for this extension install');
}

$composerJson = $registryExtension->currentBundle->meta['composer.json'];
if (!$composerJson) {
return response()->error('No valid package data found for this extension install');
}

$packageJsonName = data_get($packageJson, 'name');
$composerJsonName = data_get($composerJson, 'name');

return response()->json([
'npm' => $packageJsonName,
'composer' => $composerJsonName,
]);
}
}
34 changes: 34 additions & 0 deletions server/src/Models/RegistryExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Fleetbase\Traits\HasPublicId;
use Fleetbase\Traits\HasUuid;
use Fleetbase\Traits\Searchable;
use Illuminate\Support\Str;
use Spatie\Sluggable\HasSlug;
use Spatie\Sluggable\SlugOptions;

Expand Down Expand Up @@ -444,6 +445,39 @@ public static function findByPackageName(string $packageName): ?RegistryExtensio
})->first();
}

/**
* Lookup a registry extension based on the given package name.
*
* This method attempts to find a `RegistryExtension` that matches the provided package name. It checks multiple fields including
* `uuid`, `public_id`, and `slug`. If the package name starts with 'fleetbase/', it also attempts to match the slug extracted from the package name.
*
* Additionally, the method checks for the existence of a related `currentBundle` where the `package.json` or `composer.json` metadata
* matches the provided package name.
*
* @param string $packageName the name, UUID, public ID, or slug of the package to lookup
*
* @return RegistryExtension|null returns the found `RegistryExtension` instance or `null` if no match is found
*/
public static function lookup(string $packageName): ?RegistryExtension
{
return static::where('status', 'published')->where(function ($query) use ($packageName) {
$query->where('uuid', $packageName)
->orWhere('public_id', $packageName)
->orWhere('slug', $packageName);

// Check for fleetbase/ prefix and match slug
if (Str::startsWith($packageName, 'fleetbase/')) {
$packageSlug = explode('/', $packageName)[1] ?? null;
if ($packageSlug) {
$query->orWhere('slug', $packageSlug);
}
}
})->orWhereHas('currentBundle', function ($query) use ($packageName) {
$query->where('meta->package.json->name', $packageName)
->orWhere('meta->composer.json->name', $packageName);
})->with(['currentBundle'])->first();
}

/**
* Determines if the current extension instance is ready for submission.
*
Expand Down
3 changes: 2 additions & 1 deletion server/src/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

// Lookup package endpoint
Route::get(config('internals.api.routing.prefix', '~registry') . '/v1/lookup', 'Fleetbase\RegistryBridge\Http\Controllers\Internal\v1\RegistryController@lookupPackage');
Route::prefix(config('internals.api.routing.prefix', '~registry'))->middleware(['fleetbase.registry'])->namespace('Fleetbase\RegistryBridge\Http\Controllers')->group(
function ($router) {
/*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { module, test } from 'qunit';
import { setupRenderingTest } from 'dummy/tests/helpers';
import { render } from '@ember/test-helpers';
import { hbs } from 'ember-cli-htmlbars';

module('Integration | Component | modals/self-managed-install-instructions', function (hooks) {
setupRenderingTest(hooks);

test('it renders', async function (assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.set('myAction', function(val) { ... });

await render(hbs`<Modals::SelfManagedInstallInstructions />`);

assert.dom().hasText('');

// Template block usage:
await render(hbs`
<Modals::SelfManagedInstallInstructions>
template block text
</Modals::SelfManagedInstallInstructions>
`);

assert.dom().hasText('template block text');
});
});

0 comments on commit d6fc843

Please sign in to comment.