Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extension-manage #135

Merged
merged 24 commits into from
Sep 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:
# apply provisioning profile
# mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
# cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
echo "${{ secrets.NOTARIZE_JS }}" > build/notarize.js
echo "${{ secrets.NOTARIZE_JS }}" > scripts/notarize.js
yarn release:m1
yarn release

Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ out/
!src/workbench/node/electron/**/*.js
!src/workbench/node/request/**/*.js
!src/workbench/node/server/**/*.js
!src/workbench/browser/src/libs/
!/api/*.js
!/build/*.js
!/scripts/*.js
!*.config.js
!upload.js

scripts/notarize.js
# dependencies
node_modules
# package-lock.json
Expand Down
19 changes: 14 additions & 5 deletions electron-builder.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"appId": ".eolinker.com",
"appId": ".eoapi.io",
"asar": true,
"directories": {
"output": "release/"
Expand Down Expand Up @@ -28,8 +28,17 @@
"nsis": {
"oneClick": false,
"allowElevation": true,
"allowToChangeInstallationDirectory": true
"allowToChangeInstallationDirectory": true,
// for win - 将协议写入主机的脚本
"include": "scripts/urlProtoco.nsh"
},
"protocols": [
// for macOS - 用于在主机注册指定协议
{
"name": "eoapi",
"schemes": ["eoapi"]
}
],
"win": {
"icon": "src/app/common/images/256x256.png",
"target": [
Expand All @@ -46,14 +55,14 @@
"icon": "src/app/common/images/512x512.png",
"hardenedRuntime": true,
"gatekeeperAssess": false,
"entitlements": "build/entitlements.mac.plist",
"entitlementsInherit": "build/entitlements.mac.plist",
"entitlements": "scripts/entitlements.mac.plist",
"entitlementsInherit": "scripts/entitlements.mac.plist",
"target": ["dmg", "zip"]
},
"dmg": {
"sign": false
},
"afterSign": "build/notarize.js",
"afterSign": "scripts/notarize.js",
"linux": {
"icon": "src/app/common/images/",
"target": ["AppImage"]
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "eoapi",
"souceLocale": "zh-Hans",
"version": "1.6.0",
"version": "1.6.2",
"main": "out/app/electron-main/main.js",
"description": "A lightweight, extensible API tool",
"homepage": "https://github.com/eolinker/eoapi.git",
Expand All @@ -23,6 +23,7 @@
"electron:static": "npm run electron:tsc && electron .",
"electron:dev": "npm run electron:tsc && electron . --development",
"build": "npx patch-package && npm-run-all -s build:workbench clear:electron:tsc electron:tsc && electron-builder build",
"build:local": "npm-run-all -s build:workbench clear:electron:tsc electron:tsc && electron-builder build",
"build:static": "npm run clear:electron:tsc&&npm run electron:tsc && electron-builder build",
"release": "npm-run-all -s build:workbench electron:tsc && electron-builder --publish=always",
"release:m1": "npm-run-all -s build:workbench electron:tsc && electron-builder -m=dmg --arm64 -p onTagOrDraft",
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
9 changes: 9 additions & 0 deletions scripts/urlProtoco.nsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
!macro customInstall
DetailPrint "Register eoapi URI Handler"
DeleteRegKey HKCR "eoapi"
WriteRegStr HKCR "eoapi" "" "URL:eoapi"
WriteRegStr HKCR "eoapi" "URL Protocol" ""
WriteRegStr HKCR "eoapi\shell" "" ""
WriteRegStr HKCR "eoapi\shell\Open" "" ""
WriteRegStr HKCR "eoapi\shell\Open\command" "" "$INSTDIR\${APP_EXECUTABLE_FILENAME} %1"
!macroend
2 changes: 1 addition & 1 deletion src/app/electron-main/appView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class AppViews {
if (module && module.moduleType === ModuleType.app) {
if (module.isApp && this.mainModuleID !== module.moduleID) {
this.mainModuleID = module.moduleID;
this.sidePosition = module.sidePosition;
// this.sidePosition = module.sidePosition;
}
this.createAppView(module);

Expand Down
16 changes: 16 additions & 0 deletions src/app/electron-main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ export const subView = {
appView: null,
mainView: null,
};

// 获取单实例锁
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
// 如果获取失败,说明已经有实例在运行了,直接退出
app.quit();
}
const PROTOCOL = 'eoapi';
// app.setAsDefaultProtocolClient(PROTOCOL); // 注册协议
if (app.isPackaged) {
app.setAsDefaultProtocolClient(PROTOCOL, process.execPath, ['--']);
} else {
app.setAsDefaultProtocolClient(PROTOCOL, process.execPath, [path.resolve(process.argv[1]), '--']);
}

const eoUpdater = new EoUpdater();
const mockServer = new MockServer();
const moduleManager: ModuleManagerInterface = new ModuleManager();
Expand Down Expand Up @@ -92,6 +107,7 @@ class EoBrowserWindow {
contextIsolation: false, // false if you want to run e2e test with Spectron
},
});

proxyOpenExternal(this.win);
this.loadURL();
this.startMock();
Expand Down
3 changes: 1 addition & 2 deletions src/platform/node/extension-manager/lib/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ export class ModuleLoader implements ModuleLoaderInterface {
*/
loadModule(module: ModuleInfo): void {
if ((this.runtime === ModuleRuntime.main && ![ModuleType.system, ModuleType.app].indexOf(module.moduleType))
|| (this.runtime === ModuleRuntime.render && ![ModuleType.feature].indexOf(module.moduleType))
|| (this.runtime === ModuleRuntime.web && !module.web)) {
|| (this.runtime === ModuleRuntime.render && ![ModuleType.feature].indexOf(module.moduleType))) {
console.log(`The [${module.moduleType}] module [${module.name}] can not run in runtime [${this.runtime}].`);
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/platform/node/extension-manager/lib/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ export class ModuleManager implements ModuleManagerInterface {
if (!this.features.has(key)) {
this.features.set(key, new Map());
}
this.features.get(key).set(moduleInfo.moduleID, value);
this.features.get(key).set(moduleInfo.moduleID, { name: moduleInfo.name, ...value });
});
}
}
Expand Down
11 changes: 5 additions & 6 deletions src/platform/node/extension-manager/types/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface ModuleInfo {
// extension name
moduleName: string;
// extension type
//!TODO what usage
moduleType: ModuleType;
// extension logo
logo: string;
Expand All @@ -48,19 +49,17 @@ export interface ModuleInfo {
// inject script before start app
preload?: string;
// 判断是不是顶层App
//!TODO use feature contribution to control page
isApp?: boolean;
// web运行支持
web?: boolean;

// 模块对应上层模块ID
//!TODO what usage?
belongs?: Array<string>;
// 下层关联模块ID集合
//!TODO what usage?
sideItems?: Array<string>;
// 下层功能模块ID集合, 待移除
featureItems?: Array<string>;
// 模块路径
baseDir?: string;
// 边栏显示
sidePosition?: SidePosition;
// 配置项
configuration?: ModuleConfiguration;
/** 贡献点 */
Expand Down
2 changes: 1 addition & 1 deletion src/workbench/browser/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ dist/
/app-builds
/release
src/**/*.js
!build/*.js
!scripts/*.js
!src/karma.conf.js
!src/ng1/**/*.js
*.js.map
Expand Down
2 changes: 1 addition & 1 deletion src/workbench/browser/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ registerLocaleData(zh);
}
},
deps: [LOCALE_ID],
}
},
],
bootstrap: [AppComponent],
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<div class="overview_container">
<h1 class="fs20 fwb" i18n="@@API Index">Index</h1>
<nz-divider></nz-divider>
<section class="grid gap-8 grid-cols-2 xl:grid-cols-3">
<section class="grid grid-cols-2 gap-8 xl:grid-cols-3">
<div class="card_item" *ngFor="let item of overviewList">
<nz-card class="h-full" [nzActions]="[card]" [nzHoverable]="true">
<nz-card class="h-full" [nzActions]="[card]" [nzHoverable]="true" (click)="handleClickCard($event, item)">
<nz-card-meta [nzTitle]="item.title" [nzDescription]="item.desc"></nz-card-meta>
</nz-card>
<ng-template #card>
<eo-iconpark-icon (click)="clickCard(item)" class="mr5" name="{{ item.icon }}" size="16px"></eo-iconpark-icon>
<eo-iconpark-icon class="mr5" name="{{ item.icon }}" size="16px"></eo-iconpark-icon>
</ng-template>
</div>
</section>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ export class ApiOverviewComponent implements OnDestroy {
},
];

handleClickCard = (event, item) => {
if (event.target?.classList?.contains?.('ant-card-actions') || event.target?.closest('.ant-card-actions')) {
this.clickCard(item);
}
};

clickCard({ title, desc, type }) {
this.modal = this.modalService.create({
nzTitle: desc,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { Component, Input, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { LanguageService } from 'eo/workbench/browser/src/app/core/services/language/language.service';
import { SettingService } from 'eo/workbench/browser/src/app/core/services/settings/settings.service';
import { NzMessageService } from 'ng-zorro-antd/message';

@Component({
selector: 'eo-extension-setting',
template: `
<div
class="bg-white sticky top-0 py-[10px] border-solid border-0 border-b-[1px] z-10 mb-[3px]"
style="border-color: var(--BORDER)"
>
<button nz-button nzType="primary" (click)="handleSave()">Save</button>
</div>

<form nz-form [nzLayout]="'vertical'" [formGroup]="validateForm" class="form">
<nz-form-item nz-col class="fg1" *ngFor="let field of objectKeys(properties)">
<ng-container *ngIf="properties[field]?.label">
<nz-form-label nzFor="{{ field }}" [nzRequired]="properties[field]?.required" class="label">
{{ properties[field]?.label }}
</nz-form-label>
</ng-container>
<!-- 二级说明 -->
<div
*ngIf="properties[field]?.type !== 'boolean' && properties[field]?.description"
class="text-[12px] mb-[8px] text-gray-400"
>
{{ properties[field]?.description }}
</div>
<nz-form-control i18n-nzErrorTip nzErrorTip="Please Enter {{ properties[field]?.label }}" class="form-control">
<!-- 字符串类型 -->
<!-- <ng-container *ngIf="properties[field]?.type === 'string'"> -->
<input
type="text"
nz-input
id="{{ field }}"
[disabled]="properties[field]?.disabled"
i18n-placeholder
placeholder="{{ properties[field]?.placeholder ?? 'Please Enter ' + properties[field]?.label }}"
formControlName="{{ field }}"
[(ngModel)]="localSettings[field]"
/>
<!-- </ng-container> -->

<!-- 布尔类型 -->
<ng-container *ngIf="properties[field]?.type === 'boolean'">
<label
nz-checkbox
[(ngModel)]="localSettings[field]"
id="{{ field }}"
[nzDisabled]="properties[field]?.disabled"
formControlName="{{ field }}"
>{{ properties[field]?.description }}</label
>
</ng-container>

<!-- 数字类型 -->
<ng-container *ngIf="properties[field]?.type === 'number'">
<nz-input-number
[(ngModel)]="localSettings[field]"
id="{{ field }}"
[nzDisabled]="properties[field]?.disabled"
formControlName="{{ field }}"
>
{{ properties[field]?.description }}</nz-input-number
>
</ng-container>
</nz-form-control>
</nz-form-item>
</form>
`,
})
export class ExtensionSettingComponent implements OnInit {
@Input() configuration = {} as any;
localSettings = {} as Record<string, any>;
validateForm!: FormGroup;
objectKeys = Object.keys;
get properties() {
return this.configuration?.properties || {};
}

constructor(
public languageService: LanguageService,
private fb: FormBuilder,
private settingService: SettingService,
private message: NzMessageService
) {}

ngOnInit(): void {
this.init();
}

private init() {
this.localSettings = this.settingService.getSettings();
const controls = {};

this.setSettingsModel(this.configuration.properties, controls);

this.validateForm = this.fb.group(controls);
}

/**
* set data
*
* @param properties
*/
private setSettingsModel(properties, controls) {
// Flat configuration object
Object.keys(properties).forEach((fieldKey) => {
const props = properties[fieldKey];
this.localSettings[fieldKey] ??= props.default;
// Extensible to add more default checks
if (props.required) {
controls[fieldKey] = [null, [Validators.required]];
} else {
controls[fieldKey] = [null];
}
});
}

handleSave = () => {
this.settingService.saveSetting(this.localSettings);
window.eo?.saveSettings?.({ ...this.localSettings });
this.message.create('success', `Save Success`);
};
}
Loading