mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 20:14:49 +00:00
feature/marketplace icons (#1921)
* add registry icons, update links, clean up code (#1913) * add registry icons, update links, clean up code * remove seeding of registry icon and name * fix install wizard copy Co-authored-by: Lucy C <12953208+elvece@users.noreply.github.com> * remove references to bep and chime * fix shutdown language and remove chime from initializing screen * fix type error Co-authored-by: Matt Hill <MattDHill@users.noreply.github.com> Co-authored-by: Lucy C <12953208+elvece@users.noreply.github.com> Co-authored-by: Matt Hill <matthewonthemoon@gmail.com>
This commit is contained in:
@@ -161,7 +161,7 @@ export class AppActionsPage {
|
||||
try {
|
||||
await this.embassyApi.uninstallPackage({ id: this.pkgId })
|
||||
this.embassyApi
|
||||
.setDbValue(['ack-instructions', this.pkgId], false)
|
||||
.setDbValue<boolean>(['ack-instructions', this.pkgId], false)
|
||||
.catch(e => console.error('Failed to mark instructions as unseen', e))
|
||||
this.navCtrl.navigateRoot('/services')
|
||||
} catch (e: any) {
|
||||
|
||||
@@ -10,13 +10,26 @@
|
||||
<p>{{ manifest.version | displayEmver }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item button detail="false" (click)="copy(manifest['git-hash'])">
|
||||
<ion-item
|
||||
*ngIf="manifest['git-hash'] as gitHash; else noHash"
|
||||
button
|
||||
detail="false"
|
||||
(click)="copy(gitHash)"
|
||||
>
|
||||
<ion-label>
|
||||
<h2>Git Hash</h2>
|
||||
<p>{{ manifest['git-hash'] }}</p>
|
||||
<p>{{ gitHash }}</p>
|
||||
</ion-label>
|
||||
<ion-icon slot="end" name="copy-outline"></ion-icon>
|
||||
</ion-item>
|
||||
<ng-template #noHash>
|
||||
<ion-item>
|
||||
<ion-label>
|
||||
<h2>Git Hash</h2>
|
||||
<p>Unknown</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ng-template>
|
||||
<ion-item button detail="false" (click)="presentModalLicense()">
|
||||
<ion-label>
|
||||
<h2>License</h2>
|
||||
|
||||
@@ -109,7 +109,7 @@ export class ToButtonsPipe implements PipeTransform {
|
||||
|
||||
private async presentModalInstructions(pkg: PackageDataEntry) {
|
||||
this.apiService
|
||||
.setDbValue(['ack-instructions', pkg.manifest.id], true)
|
||||
.setDbValue<boolean>(['ack-instructions', pkg.manifest.id], true)
|
||||
.catch(e => console.error('Failed to mark instructions as seen', e))
|
||||
|
||||
const modal = await this.modalCtrl.create({
|
||||
@@ -130,19 +130,19 @@ export class ToButtonsPipe implements PipeTransform {
|
||||
const queryParams = url ? { url } : {}
|
||||
|
||||
let button: Button = {
|
||||
title: 'Marketplace',
|
||||
title: 'Marketplace Listing',
|
||||
icon: 'storefront-outline',
|
||||
action: () =>
|
||||
this.navCtrl.navigateForward([`marketplace/${pkg.manifest.id}`], {
|
||||
queryParams,
|
||||
}),
|
||||
disabled: false,
|
||||
description: 'View service in marketplace',
|
||||
description: 'View service in the marketplace',
|
||||
}
|
||||
|
||||
if (!url) {
|
||||
button.disabled = true
|
||||
button.description = 'This package was not installed from a marketplace.'
|
||||
button.description = 'This package was not installed from the marketplace'
|
||||
button.action = () => {}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,10 @@ export class DevConfigPage {
|
||||
async save() {
|
||||
this.saving = true
|
||||
try {
|
||||
await this.api.setDbValue(['dev', this.projectId, 'config'], this.code)
|
||||
await this.api.setDbValue<string>(
|
||||
['dev', this.projectId, 'config'],
|
||||
this.code,
|
||||
)
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
|
||||
@@ -56,7 +56,7 @@ export class DevInstructionsPage {
|
||||
async save() {
|
||||
this.saving = true
|
||||
try {
|
||||
await this.api.setDbValue(
|
||||
await this.api.setDbValue<string>(
|
||||
['dev', this.projectId, 'instructions'],
|
||||
this.code,
|
||||
)
|
||||
|
||||
@@ -148,7 +148,11 @@ export class DeveloperListPage {
|
||||
.replace(/warning:/g, '# Optional\n warning:')
|
||||
|
||||
const def = { name, config, instructions: SAMPLE_INSTUCTIONS }
|
||||
await this.api.setDbValue(['dev', id], def)
|
||||
await this.api.setDbValue<{
|
||||
name: string
|
||||
config: string
|
||||
instructions: string
|
||||
}>(['dev', id], def)
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
@@ -184,7 +188,7 @@ export class DeveloperListPage {
|
||||
await loader.present()
|
||||
|
||||
try {
|
||||
await this.api.setDbValue(['dev', id, 'name'], newName)
|
||||
await this.api.setDbValue<string>(['dev', id, 'name'], newName)
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
@@ -201,7 +205,7 @@ export class DeveloperListPage {
|
||||
try {
|
||||
const devDataToSave: DevData = JSON.parse(JSON.stringify(this.devData))
|
||||
delete devDataToSave[id]
|
||||
await this.api.setDbValue(['dev'], devDataToSave)
|
||||
await this.api.setDbValue<DevData>(['dev'], devDataToSave)
|
||||
} catch (e: any) {
|
||||
this.errToast.present(e)
|
||||
} finally {
|
||||
|
||||
@@ -55,7 +55,7 @@ export class DeveloperMenuPage {
|
||||
await loader.present()
|
||||
|
||||
try {
|
||||
await this.api.setDbValue(
|
||||
await this.api.setDbValue<BasicInfo>(
|
||||
['dev', this.projectId, 'basic-info'],
|
||||
basicInfo,
|
||||
)
|
||||
|
||||
@@ -151,7 +151,7 @@ export function getBasicInfoSpec(devData: DevProjectData): ConfigSpec {
|
||||
type: 'string',
|
||||
name: 'Support Site',
|
||||
description: 'URL to the support site / channel for the project',
|
||||
placeholder: 'e.g. www.start9labs.com',
|
||||
placeholder: 'e.g. start9.com/support',
|
||||
nullable: true,
|
||||
masked: false,
|
||||
copyable: false,
|
||||
@@ -161,7 +161,7 @@ export function getBasicInfoSpec(devData: DevProjectData): ConfigSpec {
|
||||
type: 'string',
|
||||
name: 'Marketing Site',
|
||||
description: 'URL to the marketing site / channel for the project',
|
||||
placeholder: 'e.g. www.start9labs.com',
|
||||
placeholder: 'e.g. start9.com',
|
||||
nullable: true,
|
||||
masked: false,
|
||||
copyable: false,
|
||||
|
||||
@@ -23,10 +23,20 @@
|
||||
</ion-row>
|
||||
<ion-row>
|
||||
<ion-col size="12">
|
||||
<h1 class="heading montserrat ion-text-center">{{ details.name }}</h1>
|
||||
<div class="heading">
|
||||
<img
|
||||
*ngIf="details.icon; else noIcon"
|
||||
[src]="'data:image/png;base64,' + details.icon | trustUrl"
|
||||
alt=""
|
||||
/>
|
||||
<ng-template #noIcon>
|
||||
<ion-icon name="storefront-outline"></ion-icon>
|
||||
</ng-template>
|
||||
<h1 class="montserrat ion-text-center">{{ details.name }}</h1>
|
||||
</div>
|
||||
<ion-button fill="clear" (click)="presentModalMarketplaceSettings()">
|
||||
<ion-icon slot="start" name="repeat-outline"></ion-icon>
|
||||
Switch Marketplaces
|
||||
Change
|
||||
</ion-button>
|
||||
<marketplace-search [(query)]="query"></marketplace-search>
|
||||
</ion-col>
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
.heading {
|
||||
font-size: 42px;
|
||||
$icon-size: 64px;
|
||||
margin-top: 32px;
|
||||
img {
|
||||
max-width: $icon-size;
|
||||
}
|
||||
h1 {
|
||||
font-size: 42px;
|
||||
}
|
||||
ion-icon {
|
||||
font-size: $icon-size;
|
||||
}
|
||||
}
|
||||
|
||||
.divider {
|
||||
|
||||
@@ -30,35 +30,36 @@ export class MarketplaceListPage {
|
||||
readonly localPkgs$ = this.patch.watch$('package-data')
|
||||
|
||||
readonly details$ = this.marketplaceService.getSelectedHost$().pipe(
|
||||
map(({ url, name }) => {
|
||||
map(({ url, name, icon }) => {
|
||||
let color: string
|
||||
let description: string
|
||||
switch (url) {
|
||||
case 'https://registry.start9.com/':
|
||||
color = 'success'
|
||||
description =
|
||||
'Services in this marketplace are packaged and maintained by the Start9 team. If you experience an issue or have a questions related to a service in this marketplace, one of our dedicated support staff will be happy to assist you.'
|
||||
'Services from this registry are packaged and maintained by the Start9 team. If you experience an issue or have a questions related to a service from this registry, one of our dedicated support staff will be happy to assist you.'
|
||||
break
|
||||
case 'https://beta-registry-0-3.start9labs.com/':
|
||||
case 'https://beta-registry.start9.com/':
|
||||
color = 'primary'
|
||||
description =
|
||||
'Services in this marketplace are undergoing active testing and may contain bugs. <b>Install at your own risk</b>. If you discover a bug or have a suggestion for improvement, please report it to the Start9 team in our community testing channel on Matrix.'
|
||||
'Services from this registry are undergoing active testing and may contain bugs. <b>Install at your own risk</b>. If you discover a bug or have a suggestion for improvement, please report it to the Start9 team in our community testing channel on Matrix.'
|
||||
break
|
||||
case 'https://community.start9labs.com/':
|
||||
case 'https://community-registry.start9.com/':
|
||||
color = 'tertiary'
|
||||
description =
|
||||
'Services in this marketplace are packaged and maintained by members of the Start9 community. <b>Install at your own risk</b>. If you experience an issue or have a question related to a service in this marketplace, please reach out to the package developer for assistance.'
|
||||
'Services from this registry are packaged and maintained by members of the Start9 community. <b>Install at your own risk</b>. If you experience an issue or have a question related to a service in this marketplace, please reach out to the package developer for assistance.'
|
||||
break
|
||||
default:
|
||||
// alt marketplace
|
||||
color = 'warning'
|
||||
description =
|
||||
'Warning. This is an <b>Alternative</b> Marketplace. Start9 cannot verify the integrity or functionality of services in this marketplace, and they may cause harm to your system. <b>Install at your own risk</b>.'
|
||||
'Warning. This is a <b>Custom</b> Registry. Start9 cannot verify the integrity or functionality of services from this registry, and they may cause harm to your system. <b>Install at your own risk</b>.'
|
||||
}
|
||||
|
||||
return {
|
||||
name,
|
||||
url,
|
||||
icon,
|
||||
color,
|
||||
description,
|
||||
}
|
||||
|
||||
@@ -99,11 +99,12 @@ export class MarketplaceShowControlsComponent {
|
||||
this.patch.watch$('ui', 'marketplace'),
|
||||
)
|
||||
|
||||
const name = marketplaces['known-hosts'][url] || url
|
||||
const name: string = marketplaces['known-hosts'][url]?.name || url
|
||||
|
||||
let originalName: string | undefined
|
||||
if (originalUrl) {
|
||||
originalName = marketplaces['known-hosts'][originalUrl] || originalUrl
|
||||
originalName =
|
||||
marketplaces['known-hosts'][originalUrl]?.name || originalUrl
|
||||
}
|
||||
|
||||
return new Promise(async resolve => {
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
</ol>
|
||||
View the full
|
||||
<a
|
||||
href="https://start9.com/latest/user-manual/connecting/connecting-lan"
|
||||
href="https://docs.start9.com/latest/user-manual/connecting/connecting-lan"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>instructions</a
|
||||
|
||||
@@ -178,7 +178,7 @@ export class ServerShowPage {
|
||||
async presentAlertRepairDisk() {
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: 'Warning',
|
||||
message: `<p>This action will attempt to preform a disk repair operation and system reboot. No data will be deleted. This action should only be executed if directed by a Start9 support specialist. We recommend backing up your device before preforming this action.</p><p>If anything happens to the device during the reboot (between the bep and chime), such as losing power, a power surge, unplugging the drive, or unplugging the Embassy, the filesystem <i>will</i> be in an unrecoverable state. Please proceed with caution.</p>`,
|
||||
message: `<p>This action will attempt to preform a disk repair operation and system reboot. No data will be deleted. This action should only be executed if directed by a Start9 support specialist. We recommend backing up your device before preforming this action.</p><p>If anything happens to the device during the reboot, such as losing power, a power surge, unplugging the drive, or unplugging the Embassy, the filesystem <i>will</i> be in an unrecoverable state. Please proceed with caution.</p>`,
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
@@ -223,7 +223,7 @@ export class ServerShowPage {
|
||||
await loader.present()
|
||||
|
||||
try {
|
||||
await this.embassyApi.setDbValue([key], value)
|
||||
await this.embassyApi.setDbValue<string>([key], value)
|
||||
} finally {
|
||||
loader.dismiss()
|
||||
}
|
||||
@@ -333,7 +333,7 @@ export class ServerShowPage {
|
||||
private async presentAlertInProgress(verb: string, message: string) {
|
||||
const alert = await this.alertCtrl.create({
|
||||
header: `${verb} In Progress...`,
|
||||
message: `Stopping all services gracefully. This can take a while.<br /><br />Your Embassy will then <b>♫ play a melody ♫</b> and become unreachable${message}`,
|
||||
message: `Stopping all services gracefully. This can take a while.<br /><br />If you have a speaker, your Embassy will <b>♫ play a melody ♫</b> before shutting down. Your Embassy will then become unreachable${message}`,
|
||||
buttons: [
|
||||
{
|
||||
text: 'OK',
|
||||
@@ -484,7 +484,7 @@ export class ServerShowPage {
|
||||
icon: 'map-outline',
|
||||
action: () =>
|
||||
window.open(
|
||||
'https://start9.com/latest/user-manual/',
|
||||
'https://docs.start9.com/latest/user-manual',
|
||||
'_blank',
|
||||
'noreferrer',
|
||||
),
|
||||
@@ -497,7 +497,7 @@ export class ServerShowPage {
|
||||
icon: 'chatbubbles-outline',
|
||||
action: () =>
|
||||
window.open(
|
||||
'https://start9.com/latest/support/contact/',
|
||||
'https://docs.start9.com/latest/support/contact',
|
||||
'_blank',
|
||||
'noreferrer',
|
||||
),
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
export class SSHKeysPage {
|
||||
loading = true
|
||||
sshKeys: SSHKey[] = []
|
||||
readonly docsUrl = 'https://start9.com/latest/user-manual/ssh'
|
||||
readonly docsUrl = 'https://docs.start9.com/latest/user-manual/ssh'
|
||||
|
||||
constructor(
|
||||
private readonly loadingCtrl: LoadingController,
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
Ethernet cable and move the device anywhere you want. Embassy will
|
||||
automatically connect to available networks.
|
||||
<a
|
||||
href="https://start9.com/latest/user-manual/wifi"
|
||||
href="https://docs.start9.com/latest/user-manual/wifi"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>View instructions</a
|
||||
|
||||
@@ -10,7 +10,14 @@
|
||||
<ion-content class="ion-padding">
|
||||
<ion-item-group *ngIf="data$ | async as data">
|
||||
<ng-container *ngFor="let host of data.hosts | keyvalue">
|
||||
<ion-item-divider> {{ host.value }} </ion-item-divider>
|
||||
<ion-item-divider>
|
||||
{{ host.value.name }}
|
||||
<img
|
||||
style="max-width: 24px"
|
||||
[src]="'data:image/png;base64,' + host.value.icon | trustUrl"
|
||||
alt=""
|
||||
/>
|
||||
</ion-item-divider>
|
||||
|
||||
<div class="ion-padding-start ion-padding-bottom">
|
||||
<ion-item *ngIf="data.errors.includes(host.key)">
|
||||
@@ -25,7 +32,7 @@
|
||||
>
|
||||
<ion-item *ngFor="let pkg of updates">
|
||||
<ng-container *ngIf="data.localPkgs[pkg.manifest.id] as local">
|
||||
<ion-avatar slot="start">
|
||||
<ion-avatar slot="start" class="service-avatar">
|
||||
<img [src]="'data:image/png;base64,' + pkg.icon | trustUrl" />
|
||||
</ion-avatar>
|
||||
<ion-label>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ion-avatar {
|
||||
.service-avatar {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
Marketplace,
|
||||
MarketplaceManifest,
|
||||
MarketplacePkg,
|
||||
StoreIdentifier,
|
||||
} from '@start9labs/marketplace'
|
||||
import { Emver } from '@start9labs/shared'
|
||||
import { Pipe, PipeTransform } from '@angular/core'
|
||||
@@ -19,7 +20,7 @@ import { combineLatest, Observable } from 'rxjs'
|
||||
import { PrimaryRendering } from '../../services/pkg-status-rendering.service'
|
||||
|
||||
interface UpdatesData {
|
||||
hosts: Record<string, string>
|
||||
hosts: Record<string, StoreIdentifier>
|
||||
marketplace: Marketplace
|
||||
localPkgs: Record<string, PackageDataEntry>
|
||||
errors: string[]
|
||||
|
||||
Reference in New Issue
Block a user