mirror of
https://github.com/Eugeny/tabby.git
synced 2025-10-04 05:54:57 +00:00
wip
This commit is contained in:
1
terminus-plugin-manager/.gitignore
vendored
Normal file
1
terminus-plugin-manager/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
dist
|
2649
terminus-plugin-manager/package-lock.json
generated
Normal file
2649
terminus-plugin-manager/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
46
terminus-plugin-manager/package.json
Normal file
46
terminus-plugin-manager/package.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "terminus-plugin-manager",
|
||||
"version": "0.0.1",
|
||||
"description": "Terminus' plugin manager",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "webpack --progress --color --display-modules",
|
||||
"watch": "webpack --progress --color --watch"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"author": "Eugene Pankov",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/mz": "0.0.31",
|
||||
"@types/node": "7.0.12",
|
||||
"@types/npm": "^2.0.28",
|
||||
"@types/semver": "^5.3.31",
|
||||
"@types/webpack-env": "1.13.0",
|
||||
"awesome-typescript-loader": "3.1.2",
|
||||
"css-loader": "^0.28.0",
|
||||
"pug": "^2.0.0-beta11",
|
||||
"pug-loader": "^2.3.0",
|
||||
"raw-loader": "^0.5.1",
|
||||
"sass-loader": "^6.0.3",
|
||||
"semver": "^5.3.0",
|
||||
"to-string-loader": "^1.1.5",
|
||||
"typescript": "^2.2.2",
|
||||
"webpack": "2.3.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/common": "4.0.1",
|
||||
"@angular/core": "4.0.1",
|
||||
"@angular/forms": "4.0.1",
|
||||
"@angular/platform-browser": "4.0.1",
|
||||
"@ng-bootstrap/ng-bootstrap": "1.0.0-alpha.22",
|
||||
"terminus-core": "*",
|
||||
"terminus-settings": "*",
|
||||
"rxjs": "5.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.16.1"
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
h3 Installed
|
||||
|
||||
.list-group
|
||||
ng-container(*ngFor='let plugin of pluginManager.installedPlugins')
|
||||
.list-group-item.flex-column.align-items-start(*ngIf='knownUpgrades[plugin.name]')
|
||||
.d-flex.w-100
|
||||
h6.mr-auto.mb-0 {{plugin.name}}
|
||||
p.mb-0.mr-3 {{plugin.version}}
|
||||
button.btn.btn-outline-primary((click)='upgradePlugin(plugin)')
|
||||
i.fa.fa-arrow-up
|
||||
span Upgrade ({{knownUpgrades[plugin.name].version}})
|
||||
small.mb-0 {{plugin.description}}
|
||||
|
||||
ng-container(*ngFor='let plugin of pluginManager.installedPlugins')
|
||||
.list-group-item.flex-column.align-items-start(*ngIf='!knownUpgrades[plugin.name]')
|
||||
.d-flex.w-100
|
||||
h6.mr-auto.mb-0 {{plugin.name}}
|
||||
p.mb-0.mr-3 {{plugin.version}}
|
||||
button.btn.btn-outline-danger((click)='uninstallPlugin(plugin)', *ngIf='!plugin.isBuiltin')
|
||||
i.fa.fa-trash-o
|
||||
small.mb-0 {{plugin.description}}
|
||||
|
||||
|
||||
h3.mt-4 Available
|
||||
|
||||
.input-group.mb-4
|
||||
.input-group-addon
|
||||
i.fa.fa-fw.fa-circle-o-notch.fa-spin(*ngIf='!availablePluginsReady')
|
||||
i.fa.fa-fw.fa-search(*ngIf='availablePluginsReady')
|
||||
input.form-control(
|
||||
type='text',
|
||||
'[(ngModel)]'='_1',
|
||||
(ngModelChange)='availablePluginsQuery$.next(_1)',
|
||||
placeholder='Search plugins'
|
||||
)
|
||||
|
||||
.list-group(*ngIf='availablePlugins$')
|
||||
ng-container(*ngFor='let plugin of (availablePlugins$|async)')
|
||||
.list-group-item.flex-column.align-items-start(*ngIf='!isAlreadyInstalled(plugin)')
|
||||
.d-flex.w-100
|
||||
h6.mr-auto.mb-0 {{plugin.name}}
|
||||
p.mb-0.mr-3 {{plugin.version}}
|
||||
button.btn.btn-outline-primary((click)='installPlugin(plugin)')
|
||||
i.fa.fa-download
|
||||
span Install
|
||||
small.mb-0 {{plugin.description}}
|
@@ -0,0 +1,8 @@
|
||||
.appearance-preview {
|
||||
padding: 10px 20px;
|
||||
margin: 0 0 10px;
|
||||
overflow: hidden;
|
||||
span {
|
||||
white-space: pre;
|
||||
}
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
import { BehaviorSubject, Observable } from 'rxjs'
|
||||
import * as fs from 'fs-promise'
|
||||
import * as path from 'path'
|
||||
import * as semver from 'semver'
|
||||
import { exec } from 'mz/child_process'
|
||||
|
||||
import { Component, Inject, ChangeDetectionStrategy } from '@angular/core'
|
||||
import { IPluginInfo, PluginManagerService } from '../services/pluginManager.service'
|
||||
|
||||
@Component({
|
||||
template: require('./pluginsSettingsTab.component.pug'),
|
||||
styles: [require('./pluginsSettingsTab.component.scss')],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class PluginsSettingsTabComponent {
|
||||
availablePlugins$: Observable<IPluginInfo[]>
|
||||
availablePluginsQuery$ = new BehaviorSubject<string>('')
|
||||
availablePluginsReady = false
|
||||
knownUpgrades: {[id: string]: IPluginInfo} = {}
|
||||
busy: boolean
|
||||
|
||||
constructor (
|
||||
public pluginManager: PluginManagerService
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit () {
|
||||
this.availablePlugins$ = this.availablePluginsQuery$
|
||||
.debounceTime(200)
|
||||
.distinctUntilChanged()
|
||||
.flatMap(query => {
|
||||
this.availablePluginsReady = false
|
||||
return this.pluginManager.listAvailable(query).do(() => {
|
||||
this.availablePluginsReady = true
|
||||
})
|
||||
})
|
||||
this.availablePlugins$.first().subscribe(available => {
|
||||
for (let plugin of this.pluginManager.installedPlugins) {
|
||||
this.knownUpgrades[plugin.name] = available.find(x => x.name === plugin.name && semver.gt(x.version, plugin.version))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
isAlreadyInstalled (plugin: IPluginInfo): boolean {
|
||||
return this.pluginManager.installedPlugins.some(x => x.name === plugin.name)
|
||||
}
|
||||
|
||||
async installPlugin (plugin: IPluginInfo): Promise<void> {
|
||||
this.busy = true
|
||||
}
|
||||
|
||||
async upgradePlugin (plugin: IPluginInfo): Promise<void> {
|
||||
return this.installPlugin(this.knownUpgrades[plugin.name])
|
||||
}
|
||||
}
|
31
terminus-plugin-manager/src/index.ts
Normal file
31
terminus-plugin-manager/src/index.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { NgModule } from '@angular/core'
|
||||
import { BrowserModule } from '@angular/platform-browser'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
|
||||
import { SettingsTabProvider } from 'terminus-settings'
|
||||
|
||||
import { PluginsSettingsTabComponent } from './components/pluginsSettingsTab.component'
|
||||
import { PluginManagerService } from './services/pluginManager.service'
|
||||
import { PluginsSettingsTabProvider } from './settings'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
NgbModule,
|
||||
],
|
||||
providers: [
|
||||
{ provide: SettingsTabProvider, useClass: PluginsSettingsTabProvider, multi: true },
|
||||
PluginManagerService,
|
||||
],
|
||||
entryComponents: [
|
||||
PluginsSettingsTabComponent,
|
||||
],
|
||||
declarations: [
|
||||
PluginsSettingsTabComponent,
|
||||
],
|
||||
})
|
||||
export default class PluginManagerModule { }
|
||||
|
||||
export { PluginManagerService }
|
@@ -0,0 +1,49 @@
|
||||
import * as fs from 'fs-promise'
|
||||
import { Observable } from 'rxjs'
|
||||
import { Injectable } from '@angular/core'
|
||||
import { Logger, LogService } from 'terminus-core'
|
||||
import axios from 'axios'
|
||||
|
||||
const NAME_PREFIX = 'terminus-'
|
||||
|
||||
export interface IPluginInfo {
|
||||
name: string
|
||||
description: string
|
||||
packageName: string
|
||||
isBuiltin: boolean
|
||||
version: string
|
||||
homepage?: string
|
||||
path?: string
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class PluginManagerService {
|
||||
logger: Logger
|
||||
builtinPluginsPath: string = (window as any).builtinPluginsPath
|
||||
userPluginsPath: string = (window as any).userPluginsPath
|
||||
installedPlugins: IPluginInfo[] = (window as any).installedPlugins
|
||||
|
||||
constructor (
|
||||
log: LogService,
|
||||
) {
|
||||
this.logger = log.create('pluginManager')
|
||||
}
|
||||
|
||||
listAvailable (query?: string): Observable<IPluginInfo[]> {
|
||||
return Observable
|
||||
.fromPromise(
|
||||
axios.get(`https://www.npmjs.com/-/search?text=${NAME_PREFIX}+${encodeURIComponent(query || '')}&from=0&size=1000`)
|
||||
)
|
||||
.map(response => response.data.objects.map(item => ({
|
||||
name: item.package.name.substring(NAME_PREFIX.length),
|
||||
packageName: item.package.name,
|
||||
description: item.package.description,
|
||||
version: item.package.version,
|
||||
homepage: item.package.links.homepage,
|
||||
})))
|
||||
.map(plugins => plugins.filter(x => x.packageName.startsWith(NAME_PREFIX)))
|
||||
}
|
||||
|
||||
async installPlugin (plugin: IPluginInfo) {
|
||||
}
|
||||
}
|
13
terminus-plugin-manager/src/settings.ts
Normal file
13
terminus-plugin-manager/src/settings.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { Injectable } from '@angular/core'
|
||||
import { SettingsTabProvider, ComponentType } from 'terminus-settings'
|
||||
|
||||
import { PluginsSettingsTabComponent } from './components/pluginsSettingsTab.component'
|
||||
|
||||
@Injectable()
|
||||
export class PluginsSettingsTabProvider extends SettingsTabProvider {
|
||||
title = 'Plugins'
|
||||
|
||||
getComponentType (): ComponentType {
|
||||
return PluginsSettingsTabComponent
|
||||
}
|
||||
}
|
26
terminus-plugin-manager/tsconfig.json
Normal file
26
terminus-plugin-manager/tsconfig.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "src",
|
||||
"module": "commonjs",
|
||||
"target": "es2016",
|
||||
"declaration": false,
|
||||
"noImplicitAny": false,
|
||||
"removeComments": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"sourceMap": true,
|
||||
"noUnusedParameters": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUnusedParameters": true,
|
||||
"noUnusedLocals": true,
|
||||
"declaration": true,
|
||||
"declarationDir": "dist",
|
||||
"lib": [
|
||||
"dom",
|
||||
"es2015",
|
||||
"es7"
|
||||
]
|
||||
},
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
49
terminus-plugin-manager/webpack.config.js
Normal file
49
terminus-plugin-manager/webpack.config.js
Normal file
@@ -0,0 +1,49 @@
|
||||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
target: 'node',
|
||||
entry: 'src/index.ts',
|
||||
devtool: 'source-map',
|
||||
context: __dirname,
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'index.js',
|
||||
pathinfo: true,
|
||||
libraryTarget: 'umd',
|
||||
devtoolModuleFilenameTemplate: 'webpack-terminus-plugin-manager:///[resource-path]',
|
||||
},
|
||||
resolve: {
|
||||
modules: ['.', 'src', 'node_modules', '../app/node_modules'].map(x => path.join(__dirname, x)),
|
||||
extensions: ['.ts', '.js'],
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.ts$/,
|
||||
loader: 'awesome-typescript-loader',
|
||||
query: {
|
||||
configFileName: path.resolve(__dirname, 'tsconfig.json'),
|
||||
paths: {
|
||||
"terminus-*": [path.resolve(__dirname, '../terminus-*')],
|
||||
"*": [path.resolve(__dirname, '../app/node_modules/*')],
|
||||
}
|
||||
}
|
||||
},
|
||||
{ test: /\.pug$/, use: ['apply-loader', 'pug-loader'] },
|
||||
{ test: /\.scss$/, use: ['to-string-loader', 'css-loader', 'sass-loader'] },
|
||||
]
|
||||
},
|
||||
externals: [
|
||||
'fs',
|
||||
'fs-promise',
|
||||
'font-manager',
|
||||
'path',
|
||||
'node-pty',
|
||||
'mz/child_process',
|
||||
'winreg',
|
||||
/^rxjs/,
|
||||
/^@angular/,
|
||||
/^@ng-bootstrap/,
|
||||
/^terminus-/,
|
||||
]
|
||||
}
|
Reference in New Issue
Block a user