mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-30 04:01:58 +00:00
rename frontend to web and update contributing guide (#2509)
* rename frontend to web and update contributing guide * rename this time * fix build * restructure rust code * update documentation * update descriptions * Update CONTRIBUTING.md Co-authored-by: J H <2364004+Blu-J@users.noreply.github.com> --------- Co-authored-by: Aiden McClelland <me@drbonez.dev> Co-authored-by: Aiden McClelland <3732071+dr-bonez@users.noreply.github.com> Co-authored-by: J H <2364004+Blu-J@users.noreply.github.com>
This commit is contained in:
12
web/projects/shared/src/pipes/emver/emver.module.ts
Normal file
12
web/projects/shared/src/pipes/emver/emver.module.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import {
|
||||
EmverComparesPipe,
|
||||
EmverDisplayPipe,
|
||||
EmverSatisfiesPipe,
|
||||
} from './emver.pipe'
|
||||
|
||||
@NgModule({
|
||||
declarations: [EmverComparesPipe, EmverDisplayPipe, EmverSatisfiesPipe],
|
||||
exports: [EmverComparesPipe, EmverDisplayPipe, EmverSatisfiesPipe],
|
||||
})
|
||||
export class EmverPipesModule {}
|
||||
52
web/projects/shared/src/pipes/emver/emver.pipe.ts
Normal file
52
web/projects/shared/src/pipes/emver/emver.pipe.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core'
|
||||
import { Emver } from '../../services/emver.service'
|
||||
|
||||
@Pipe({
|
||||
name: 'satisfiesEmver',
|
||||
})
|
||||
export class EmverSatisfiesPipe implements PipeTransform {
|
||||
constructor(private readonly emver: Emver) {}
|
||||
|
||||
transform(versionUnderTest?: string, range?: string): boolean {
|
||||
return (
|
||||
!!versionUnderTest &&
|
||||
!!range &&
|
||||
this.emver.satisfies(versionUnderTest, range)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Pipe({
|
||||
name: 'compareEmver',
|
||||
})
|
||||
export class EmverComparesPipe implements PipeTransform {
|
||||
constructor(private readonly emver: Emver) {}
|
||||
|
||||
transform(first: string, second: string): SemverResult {
|
||||
try {
|
||||
return this.emver.compare(first, second) as SemverResult
|
||||
} catch (e) {
|
||||
console.error(`emver comparison failed`, e, first, second)
|
||||
return 'comparison-impossible'
|
||||
}
|
||||
}
|
||||
}
|
||||
// left compared to right - if 1, version on left is higher; if 0, values the same; if -1, version on left is lower
|
||||
type SemverResult = 0 | 1 | -1 | 'comparison-impossible'
|
||||
|
||||
@Pipe({
|
||||
name: 'displayEmver',
|
||||
})
|
||||
export class EmverDisplayPipe implements PipeTransform {
|
||||
constructor() {}
|
||||
|
||||
transform(version: string): string {
|
||||
return displayEmver(version)
|
||||
}
|
||||
}
|
||||
|
||||
export function displayEmver(version: string): string {
|
||||
const vs = version.split('.')
|
||||
if (vs.length === 4) return `${vs[0]}.${vs[1]}.${vs[2]}~${vs[3]}`
|
||||
return version
|
||||
}
|
||||
8
web/projects/shared/src/pipes/guid/guid.module.ts
Normal file
8
web/projects/shared/src/pipes/guid/guid.module.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { GuidPipe } from './guid.pipe'
|
||||
|
||||
@NgModule({
|
||||
declarations: [GuidPipe],
|
||||
exports: [GuidPipe],
|
||||
})
|
||||
export class GuidPipePipesModule {}
|
||||
11
web/projects/shared/src/pipes/guid/guid.pipe.ts
Normal file
11
web/projects/shared/src/pipes/guid/guid.pipe.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core'
|
||||
import { DiskInfo } from '../../types/api'
|
||||
|
||||
@Pipe({
|
||||
name: 'guid',
|
||||
})
|
||||
export class GuidPipe implements PipeTransform {
|
||||
transform(disk: DiskInfo): string | null {
|
||||
return disk.guid || disk.partitions.find(p => p.guid)?.guid || null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { MarkdownPipe } from './markdown.pipe'
|
||||
|
||||
@NgModule({
|
||||
declarations: [MarkdownPipe],
|
||||
exports: [MarkdownPipe],
|
||||
})
|
||||
export class MarkdownPipeModule {}
|
||||
28
web/projects/shared/src/pipes/markdown/markdown.pipe.ts
Normal file
28
web/projects/shared/src/pipes/markdown/markdown.pipe.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core'
|
||||
import { marked } from 'marked'
|
||||
import * as DOMPurify from 'dompurify'
|
||||
|
||||
@Pipe({
|
||||
name: 'markdown',
|
||||
})
|
||||
export class MarkdownPipe implements PipeTransform {
|
||||
transform(value: string): string {
|
||||
if (value && value.length > 0) {
|
||||
// convert markdown to html
|
||||
const html = marked(value)
|
||||
// sanitize html
|
||||
const sanitized = DOMPurify.sanitize(html)
|
||||
// parse html to find all links
|
||||
let parser = new DOMParser()
|
||||
const doc = parser.parseFromString(sanitized, 'text/html')
|
||||
const links = Array.from(doc.getElementsByTagName('a'))
|
||||
// add target="_blank" to every link
|
||||
links.forEach(link => {
|
||||
link.setAttribute('target', '_blank')
|
||||
})
|
||||
// return new html string
|
||||
return doc.documentElement.innerHTML
|
||||
}
|
||||
return value
|
||||
}
|
||||
}
|
||||
12
web/projects/shared/src/pipes/shared/empty.pipe.ts
Normal file
12
web/projects/shared/src/pipes/shared/empty.pipe.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core'
|
||||
import { isEmptyObject } from '../../util/misc.util'
|
||||
|
||||
@Pipe({
|
||||
name: 'empty',
|
||||
})
|
||||
export class EmptyPipe implements PipeTransform {
|
||||
transform(val: object | [] = {}): boolean {
|
||||
if (Array.isArray(val)) return !val.length
|
||||
return isEmptyObject(val)
|
||||
}
|
||||
}
|
||||
10
web/projects/shared/src/pipes/shared/includes.pipe.ts
Normal file
10
web/projects/shared/src/pipes/shared/includes.pipe.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core'
|
||||
|
||||
@Pipe({
|
||||
name: 'includes',
|
||||
})
|
||||
export class IncludesPipe implements PipeTransform {
|
||||
transform<T>(list: T[], val: T): boolean {
|
||||
return list.includes(val)
|
||||
}
|
||||
}
|
||||
10
web/projects/shared/src/pipes/shared/shared.module.ts
Normal file
10
web/projects/shared/src/pipes/shared/shared.module.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { IncludesPipe } from './includes.pipe'
|
||||
import { EmptyPipe } from './empty.pipe'
|
||||
import { TrustUrlPipe } from './trust.pipe'
|
||||
|
||||
@NgModule({
|
||||
declarations: [IncludesPipe, EmptyPipe, TrustUrlPipe],
|
||||
exports: [IncludesPipe, EmptyPipe, TrustUrlPipe],
|
||||
})
|
||||
export class SharedPipesModule {}
|
||||
13
web/projects/shared/src/pipes/shared/trust.pipe.ts
Normal file
13
web/projects/shared/src/pipes/shared/trust.pipe.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core'
|
||||
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'
|
||||
|
||||
@Pipe({
|
||||
name: 'trustUrl',
|
||||
})
|
||||
export class TrustUrlPipe implements PipeTransform {
|
||||
constructor(private readonly sanitizer: DomSanitizer) {}
|
||||
|
||||
transform(base64Icon: string): SafeResourceUrl {
|
||||
return this.sanitizer.bypassSecurityTrustResourceUrl(base64Icon)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { ConvertBytesPipe, DurationToSecondsPipe } from './unit-conversion.pipe'
|
||||
|
||||
@NgModule({
|
||||
declarations: [ConvertBytesPipe, DurationToSecondsPipe],
|
||||
exports: [ConvertBytesPipe, DurationToSecondsPipe],
|
||||
})
|
||||
export class UnitConversionPipesModule {}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core'
|
||||
|
||||
// converts bytes to gigabytes
|
||||
@Pipe({
|
||||
name: 'convertBytes',
|
||||
})
|
||||
export class ConvertBytesPipe implements PipeTransform {
|
||||
transform(bytes: number): string {
|
||||
if (bytes === 0) return '0 Bytes'
|
||||
|
||||
const k = 1024
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
||||
|
||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]
|
||||
}
|
||||
}
|
||||
|
||||
@Pipe({
|
||||
name: 'durationToSeconds',
|
||||
})
|
||||
export class DurationToSecondsPipe implements PipeTransform {
|
||||
transform(duration?: string | null): number {
|
||||
if (!duration) return 0
|
||||
const [, num, , unit] =
|
||||
duration.match(/^([0-9]*(\.[0-9]+)?)(ns|µs|ms|s|m|d)$/) || []
|
||||
return Number(num) * unitsToSeconds[unit]
|
||||
}
|
||||
}
|
||||
|
||||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||
|
||||
const unitsToSeconds: Record<string, number> = {
|
||||
ns: 1e-9,
|
||||
µs: 1e-6,
|
||||
ms: 0.001,
|
||||
s: 1,
|
||||
m: 60,
|
||||
h: 3600,
|
||||
d: 86400,
|
||||
}
|
||||
Reference in New Issue
Block a user