mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-04-04 22:39:46 +00:00
0.2.5 initial commit
Makefile incomplete
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
import { WifiAddPage } from './wifi-add.page'
|
||||
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
|
||||
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: WifiAddPage,
|
||||
},
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
PwaBackComponentModule,
|
||||
BadgeMenuComponentModule,
|
||||
],
|
||||
declarations: [WifiAddPage],
|
||||
})
|
||||
export class WifiAddPageModule { }
|
||||
@@ -0,0 +1,52 @@
|
||||
<ion-header>
|
||||
<ion-buttons slot="start">
|
||||
<pwa-back-button></pwa-back-button>
|
||||
</ion-buttons>
|
||||
<ion-toolbar>
|
||||
<ion-title>Add Network</ion-title>
|
||||
</ion-toolbar>
|
||||
<ion-buttons slot="end">
|
||||
<badge-menu-button></badge-menu-button>
|
||||
</ion-buttons>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding-top">
|
||||
|
||||
<ion-item *ngIf="error">
|
||||
<ion-text class="ion-text-wrap" color="danger">{{ error }}</ion-text>
|
||||
</ion-item>
|
||||
|
||||
<ion-item-group>
|
||||
<ion-item>
|
||||
<ion-label>Select Country</ion-label>
|
||||
<ion-select slot="end" placeholder="Select" [(ngModel)]="countryCode" [selectedText]="countryCode">
|
||||
<ion-select-option *ngFor="let country of countries | keyvalue : asIsOrder" [value]="country.key">
|
||||
{{ country.key }} - {{ country.value }}
|
||||
</ion-select-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
<ion-item-divider>Network and Password</ion-item-divider>
|
||||
<ion-item>
|
||||
<ion-input placeholder="Network Name (SSID)" [(ngModel)]="ssid"></ion-input>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-input type="password" placeholder="Password" [(ngModel)]="password"></ion-input>
|
||||
</ion-item>
|
||||
</ion-item-group>
|
||||
|
||||
<ion-grid style="margin-top: 40px;">
|
||||
<ion-row>
|
||||
<ion-col size="6">
|
||||
<ion-button [disabled]="!ssid" expand="block" fill="outline" color="primary" (click)="add()">
|
||||
Add
|
||||
</ion-button>
|
||||
</ion-col>
|
||||
<ion-col size="6">
|
||||
<ion-button [disabled]="!ssid" expand="block" fill="outline" color="success" (click)="addAndConnect()">
|
||||
Add and Connect
|
||||
</ion-button>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
|
||||
</ion-content>
|
||||
@@ -0,0 +1,67 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { NavController } from '@ionic/angular'
|
||||
import { ApiService } from 'src/app/services/api/api.service'
|
||||
import { WifiService } from '../wifi.service'
|
||||
import { LoaderService } from 'src/app/services/loader.service'
|
||||
|
||||
@Component({
|
||||
selector: 'wifi-add',
|
||||
templateUrl: 'wifi-add.page.html',
|
||||
styleUrls: ['wifi-add.page.scss'],
|
||||
})
|
||||
export class WifiAddPage {
|
||||
countries = require('../../../../util/countries.json')
|
||||
countryCode = 'US'
|
||||
ssid = ''
|
||||
password = ''
|
||||
error = ''
|
||||
|
||||
constructor (
|
||||
private readonly navCtrl: NavController,
|
||||
private readonly apiService: ApiService,
|
||||
private readonly loader: LoaderService,
|
||||
private readonly wifiService: WifiService,
|
||||
) { }
|
||||
|
||||
async add (): Promise<void> {
|
||||
this.loader.of({
|
||||
message: 'Saving...',
|
||||
spinner: 'lines',
|
||||
cssClass: 'loader',
|
||||
}).displayDuringAsync( async () => {
|
||||
await this.apiService.addWifi(this.ssid, this.password, this.countryCode, false)
|
||||
this.wifiService.addWifi(this.ssid)
|
||||
this.ssid = ''
|
||||
this.password = ''
|
||||
this.error = ''
|
||||
this.navCtrl.back()
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
this.error = e.message
|
||||
})
|
||||
}
|
||||
|
||||
async addAndConnect (): Promise<void> {
|
||||
this.loader.of({
|
||||
message: 'Connecting. This could take while...',
|
||||
spinner: 'lines',
|
||||
cssClass: 'loader',
|
||||
}).displayDuringAsync( async () => {
|
||||
await this.apiService.addWifi(this.ssid, this.password, this.countryCode, true)
|
||||
const success = await this.wifiService.confirmWifi(this.ssid)
|
||||
if (!success) { return }
|
||||
this.wifiService.addWifi(this.ssid)
|
||||
this.ssid = ''
|
||||
this.password = ''
|
||||
this.error = ''
|
||||
this.navCtrl.back()
|
||||
}).catch (e => {
|
||||
console.error(e)
|
||||
this.error = e.message
|
||||
})
|
||||
}
|
||||
|
||||
asIsOrder (a: any, b: any) {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
30
ui/src/app/pages/server-routes/wifi/wifi.module.ts
Normal file
30
ui/src/app/pages/server-routes/wifi/wifi.module.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { CommonModule } from '@angular/common'
|
||||
import { IonicModule } from '@ionic/angular'
|
||||
import { RouterModule, Routes } from '@angular/router'
|
||||
import { WifiListPage } from './wifi.page'
|
||||
import { PwaBackComponentModule } from 'src/app/components/pwa-back-button/pwa-back.component.module'
|
||||
import { BadgeMenuComponentModule } from 'src/app/components/badge-menu-button/badge-menu.component.module'
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: WifiListPage,
|
||||
},
|
||||
{
|
||||
path: 'add',
|
||||
loadChildren: () => import('./wifi-add/wifi-add.module').then(m => m.WifiAddPageModule),
|
||||
},
|
||||
]
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
RouterModule.forChild(routes),
|
||||
PwaBackComponentModule,
|
||||
BadgeMenuComponentModule,
|
||||
],
|
||||
declarations: [WifiListPage],
|
||||
})
|
||||
export class WifiListPageModule { }
|
||||
47
ui/src/app/pages/server-routes/wifi/wifi.page.html
Normal file
47
ui/src/app/pages/server-routes/wifi/wifi.page.html
Normal file
@@ -0,0 +1,47 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<pwa-back-button></pwa-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Wifi</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<badge-menu-button></badge-menu-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding-top">
|
||||
|
||||
<ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
|
||||
<ion-refresher-content pullingIcon="lines" refreshingSpinner="lines"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<ion-item *ngIf="error">
|
||||
<ion-text class="ion-text-wrap" color="danger">{{ error }}</ion-text>
|
||||
</ion-item>
|
||||
|
||||
<ion-item-group>
|
||||
<ion-item>
|
||||
<ion-label class="ion-text-wrap">
|
||||
<p>
|
||||
Add WiFi credentials to your Embassy so it can connect to the Internet without an ethernet cable.
|
||||
</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item-divider class="borderless"></ion-item-divider>
|
||||
|
||||
<ion-item-divider>Saved Networks</ion-item-divider>
|
||||
<ion-item button detail="false" *ngFor="let ssid of (server.wifi | async)?.ssids" (click)="presentAction(ssid)">
|
||||
<ion-label>{{ ssid }}</ion-label>
|
||||
<ion-icon *ngIf="ssid === (server.wifi | async).current" name="wifi" color="success"></ion-icon>
|
||||
</ion-item>
|
||||
</ion-item-group>
|
||||
|
||||
<ion-fab vertical="bottom" horizontal="end" slot="fixed">
|
||||
<ion-fab-button [routerLink]="['add']" class="fab-button">
|
||||
<ion-icon name="add"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab>
|
||||
|
||||
</ion-content>
|
||||
0
ui/src/app/pages/server-routes/wifi/wifi.page.scss
Normal file
0
ui/src/app/pages/server-routes/wifi/wifi.page.scss
Normal file
102
ui/src/app/pages/server-routes/wifi/wifi.page.ts
Normal file
102
ui/src/app/pages/server-routes/wifi/wifi.page.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import { Component } from '@angular/core'
|
||||
import { ActionSheetController } from '@ionic/angular'
|
||||
import { ApiService } from 'src/app/services/api/api.service'
|
||||
import { ActionSheetButton } from '@ionic/core'
|
||||
import { pauseFor } from 'src/app/util/misc.util'
|
||||
import { WifiService } from './wifi.service'
|
||||
import { PropertySubject } from 'src/app/util/property-subject.util'
|
||||
import { S9Server } from 'src/app/models/server-model'
|
||||
import { LoaderService } from 'src/app/services/loader.service'
|
||||
import { ModelPreload } from 'src/app/models/model-preload'
|
||||
|
||||
@Component({
|
||||
selector: 'wifi',
|
||||
templateUrl: 'wifi.page.html',
|
||||
styleUrls: ['wifi.page.scss'],
|
||||
})
|
||||
export class WifiListPage {
|
||||
server: PropertySubject<S9Server> = { } as any
|
||||
error: string
|
||||
|
||||
constructor (
|
||||
private readonly apiService: ApiService,
|
||||
private readonly loader: LoaderService,
|
||||
private readonly actionCtrl: ActionSheetController,
|
||||
private readonly wifiService: WifiService,
|
||||
private readonly preload: ModelPreload,
|
||||
) { }
|
||||
|
||||
async ngOnInit () {
|
||||
this.loader.displayDuring$(
|
||||
this.preload.server(),
|
||||
).subscribe(s => this.server = s)
|
||||
}
|
||||
|
||||
async doRefresh (event: any) {
|
||||
await Promise.all([
|
||||
this.apiService.getServer(),
|
||||
pauseFor(600),
|
||||
])
|
||||
event.target.complete()
|
||||
}
|
||||
|
||||
async presentAction (ssid: string) {
|
||||
const buttons: ActionSheetButton[] = [
|
||||
{
|
||||
text: 'Forget',
|
||||
cssClass: 'alert-danger',
|
||||
handler: () => {
|
||||
this.delete(ssid)
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
if (ssid !== this.server.wifi.getValue().current) {
|
||||
buttons.unshift(
|
||||
{
|
||||
text: 'Connect',
|
||||
handler: () => {
|
||||
this.connect(ssid)
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
const action = await this.actionCtrl.create({
|
||||
buttons,
|
||||
})
|
||||
|
||||
await action.present()
|
||||
}
|
||||
|
||||
// Let's add country code here.
|
||||
async connect (ssid: string): Promise<void> {
|
||||
this.loader.of({
|
||||
message: 'Connecting. This could take while...',
|
||||
spinner: 'lines',
|
||||
cssClass: 'loader',
|
||||
}).displayDuringAsync(async () => {
|
||||
await this.apiService.connectWifi(ssid)
|
||||
await this.wifiService.confirmWifi(ssid)
|
||||
this.error = ''
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
this.error = e.message
|
||||
})
|
||||
}
|
||||
|
||||
async delete (ssid: string): Promise<void> {
|
||||
this.loader.of({
|
||||
message: 'Deleting...',
|
||||
spinner: 'lines',
|
||||
cssClass: 'loader',
|
||||
}).displayDuringAsync( async () => {
|
||||
await this.apiService.deleteWifi(ssid)
|
||||
this.wifiService.removeWifi(ssid)
|
||||
this.error = ''
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
this.error = e.message
|
||||
})
|
||||
}
|
||||
}
|
||||
80
ui/src/app/pages/server-routes/wifi/wifi.service.ts
Normal file
80
ui/src/app/pages/server-routes/wifi/wifi.service.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { ToastController } from '@ionic/angular'
|
||||
import { ApiService } from 'src/app/services/api/api.service'
|
||||
import { pauseFor } from 'src/app/util/misc.util'
|
||||
import { ServerModel } from 'src/app/models/server-model'
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class WifiService {
|
||||
|
||||
constructor (
|
||||
private readonly apiService: ApiService,
|
||||
private readonly toastCtrl: ToastController,
|
||||
private readonly serverModel: ServerModel,
|
||||
) { }
|
||||
|
||||
addWifi (ssid: string): void {
|
||||
const wifi = this.serverModel.peek().wifi
|
||||
this.serverModel.update({ wifi: { ...wifi, ssids: [...new Set([ssid, ...wifi.ssids])] } })
|
||||
}
|
||||
|
||||
removeWifi (ssid: string): void {
|
||||
const wifi = this.serverModel.peek().wifi
|
||||
this.serverModel.update({ wifi: { ...wifi, ssids: wifi.ssids.filter(s => s !== ssid) } })
|
||||
}
|
||||
|
||||
async confirmWifi (ssid: string): Promise<boolean> {
|
||||
const timeout = 4000
|
||||
const maxAttempts = 5
|
||||
let attempts = 0
|
||||
|
||||
while (attempts < maxAttempts) {
|
||||
try {
|
||||
const start = new Date().valueOf()
|
||||
const { current, ssids } = (await this.apiService.getServer(timeout)).wifi
|
||||
const end = new Date().valueOf()
|
||||
if (current === ssid) {
|
||||
this.serverModel.update({ wifi: { current, ssids } })
|
||||
break
|
||||
} else {
|
||||
attempts++
|
||||
const diff = end - start
|
||||
await pauseFor(Math.max(0, timeout - diff))
|
||||
if (attempts === maxAttempts) {
|
||||
this.serverModel.update({ wifi: { current, ssids } })
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
attempts++
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
if (this.serverModel.peek().wifi.current === ssid) {
|
||||
return true
|
||||
} else {
|
||||
const toast = await this.toastCtrl.create({
|
||||
header: 'Failed to connect:',
|
||||
message: `Check credentials and try again`,
|
||||
position: 'bottom',
|
||||
duration: 4000,
|
||||
buttons: [
|
||||
{
|
||||
side: 'start',
|
||||
icon: 'close',
|
||||
handler: () => {
|
||||
return true
|
||||
},
|
||||
},
|
||||
],
|
||||
cssClass: 'notification-toast',
|
||||
})
|
||||
|
||||
setTimeout(() => toast.present(), 300)
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user