Skip to content
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
19 changes: 16 additions & 3 deletions astrbot/dashboard/routes/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1262,12 +1262,23 @@ def _get_plugin_installed_at(self, plugin) -> str | None:
async def get_plugins(self):
_plugin_resp = []
plugin_name = request.args.get("name")
for plugin in self.plugin_manager.context.get_all_stars():
if plugin_name and plugin.name != plugin_name:
continue

plugins = [
p
for p in self.plugin_manager.context.get_all_stars()
if not (plugin_name and p.name != plugin_name)
]

async def process_plugin(plugin):
logo_url = None
if plugin.logo_path:
logo_url = await self.get_plugin_logo_token(plugin.logo_path)
pages = await self._discover_plugin_pages(plugin)
Comment thread
lxfight marked this conversation as resolved.
return plugin, logo_url, pages

results = await asyncio.gather(*(process_plugin(p) for p in plugins))

for plugin, logo_url, pages in results:
_t = {
"name": plugin.name,
"repo": "" if plugin.repo is None else plugin.repo,
Expand All @@ -1283,6 +1294,7 @@ async def get_plugins(self):
"astrbot_version": plugin.astrbot_version,
"installed_at": self._get_plugin_installed_at(plugin),
"i18n": plugin.i18n,
"pages": [p.name for p in pages],
}
# 检查是否为全空的幽灵插件
if not any(
Expand All @@ -1296,6 +1308,7 @@ async def get_plugins(self):
):
continue
_plugin_resp.append(_t)
_plugin_resp.append(_t)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

return (
Response()
.ok(_plugin_resp, message=self.plugin_manager.failed_plugin_info)
Expand Down
23 changes: 23 additions & 0 deletions dashboard/src/components/shared/ExtensionCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,13 @@ const emit = defineEmits([
"view-readme",
"view-changelog",
"toggle-pin",
"open-webui",
]);

const hasPages = computed(() => {
return Array.isArray(props.extension?.pages) && props.extension.pages.length > 0;
});

const showUninstallDialog = ref(false);

const attrs = useAttrs();
Expand Down Expand Up @@ -130,6 +135,10 @@ const togglePin = () => {
emit("toggle-pin", props.extension);
};

const openWebui = () => {
emit("open-webui", props.extension);
};

</script>

<template>
Expand Down Expand Up @@ -322,6 +331,20 @@ const togglePin = () => {
</template>
</v-tooltip>

<v-tooltip v-if="hasPages" location="top" :text="tm('buttons.openWebui')">
<template v-slot:activator="{ props: actionProps }">
<v-btn
v-bind="actionProps"
icon="mdi-monitor-dashboard"
size="small"
variant="tonal"
color="primary"
:disabled="!extension.activated"
@click.stop="openWebui"
></v-btn>
</template>
</v-tooltip>
Comment thread
lxfight marked this conversation as resolved.

<v-tooltip location="top" :text="tm('card.actions.pluginConfig')">
<template v-slot:activator="{ props: actionProps }">
<v-btn
Expand Down
1 change: 1 addition & 0 deletions dashboard/src/i18n/locales/en-US/features/extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"viewRepo": "Repository",
"openPages": "Pages",
"openPage": "Open",
"openWebui": "Open Plugin UI",
"close": "Close",
"save": "Save",
"saveAndClose": "Save and Close",
Expand Down
1 change: 1 addition & 0 deletions dashboard/src/i18n/locales/ru-RU/features/extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"viewRepo": "Репозиторий",
"openPages": "Pages",
"openPage": "Открыть",
"openWebui": "Открыть UI плагина",
"close": "Закрыть",
"save": "Сохранить",
"saveAndClose": "Сохранить и закрыть",
Expand Down
1 change: 1 addition & 0 deletions dashboard/src/i18n/locales/zh-CN/features/extension.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"viewRepo": "仓库",
"openPages": "Pages",
"openPage": "打开",
"openWebui": "打开插件UI界面",
"close": "关闭",
"save": "保存",
"saveAndClose": "保存并关闭",
Expand Down
4 changes: 2 additions & 2 deletions dashboard/src/views/PluginPagePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -513,13 +513,13 @@ watch(locale, () => {

.plugin-page-frame {
width: 100%;
min-height: calc(100vh - 220px);
min-height: calc(100vh - 140px);
border: 0;
background: transparent;
}

.plugin-page-state {
min-height: calc(100vh - 220px);
min-height: calc(100vh - 140px);
display: flex;
align-items: center;
justify-content: center;
Expand Down
13 changes: 13 additions & 0 deletions dashboard/src/views/extension/InstalledPluginsTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,18 @@ const openPluginDetail = (extension) => {
});
};

const openPluginWebui = (extension) => {
const pages = extension?.pages;
if (!Array.isArray(pages) || pages.length === 0 || !extension?.name) return;
router.push({
name: "PluginPage",
params: {
pluginName: extension.name,
pageName: pages[0],
},
});
};

const pinnedExtensionNames = ref(readPinnedExtensions());

const pinnedExtensionOrder = computed(() => {
Expand Down Expand Up @@ -344,6 +356,7 @@ const togglePinnedExtension = (extension) => {
@view-handlers="showPluginInfo(extension)"
@view-readme="viewReadme(extension)"
@view-changelog="viewChangelog(extension)"
@open-webui="openPluginWebui(extension)"
>
</ExtensionCard>
</v-col>
Expand Down
15 changes: 11 additions & 4 deletions tests/test_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,9 @@ async def test_plugin_get_excludes_scanned_pages(
)
assert plugin["activated"] is True
assert "page" not in plugin
assert "pages" not in plugin
assert "pages" in plugin
assert isinstance(plugin["pages"], list)
assert PLUGIN_PAGE_DEMO_PAGE_NAME in plugin["pages"]


@pytest.mark.asyncio
Expand Down Expand Up @@ -1433,9 +1435,14 @@ async def test_plugins(
assert response.status_code == 200
data = await response.get_json()
assert data["status"] == "ok"
assert len(data["data"]) == 1
assert "components" not in data["data"][0]
installed_at = data["data"][0]["installed_at"]
assert len(data["data"]) >= 1
target = next(
(item for item in data["data"] if item["name"] == test_plugin_name),
None,
)
assert target is not None
assert "components" not in target
installed_at = target["installed_at"]
assert installed_at is not None
datetime.fromisoformat(installed_at)

Expand Down
Loading