mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2024-12-18 20:17:50 +00:00
upgraded code
This commit is contained in:
parent
a2582a650b
commit
ef7f0f30ad
@ -1,13 +1,9 @@
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from fastapi.responses import PlainTextResponse
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import APIRouter, HTTPException, Query
|
||||
from fastapi.responses import PlainTextResponse
|
||||
from fastapi import FastAPI, File, UploadFile, HTTPException, APIRouter, BackgroundTasks
|
||||
from fastapi.responses import JSONResponse, StreamingResponse, PlainTextResponse
|
||||
from pydantic import BaseModel, Field
|
||||
from fastapi.responses import FileResponse
|
||||
from lollms_webui import LOLLMSWebUI
|
||||
from pydantic import BaseModel
|
||||
from packaging import version
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import uuid
|
||||
@ -17,7 +13,6 @@ import yaml
|
||||
from lollms.security import check_access, sanitize_path
|
||||
import os
|
||||
import subprocess
|
||||
import yaml
|
||||
import uuid
|
||||
import platform
|
||||
from ascii_colors import ASCIIColors, trace_exception
|
||||
@ -34,13 +29,15 @@ def check_lollms_models_zoo():
|
||||
ASCIIColors.execute_with_animation("Checking zip library.", check_lollms_models_zoo)
|
||||
|
||||
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from fastapi.responses import StreamingResponse
|
||||
from pydantic import BaseModel
|
||||
from pathlib import Path
|
||||
import zipfile
|
||||
import io
|
||||
|
||||
|
||||
import shutil
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
lollmsElfServer: LOLLMSWebUI = LOLLMSWebUI.get_instance()
|
||||
|
||||
@ -48,7 +45,23 @@ class AuthRequest(BaseModel):
|
||||
client_id: str
|
||||
|
||||
class AppInfo:
|
||||
def __init__(self, uid: str, name: str, folder_name: str, icon: str, category:str, description: str, author:str, version:str, model_name:str, disclaimer:str, installed: bool):
|
||||
def __init__(
|
||||
self,
|
||||
uid: str,
|
||||
name: str,
|
||||
folder_name: str,
|
||||
icon: str,
|
||||
category:str,
|
||||
description: str,
|
||||
author:str,
|
||||
version:str,
|
||||
model_name:str,
|
||||
disclaimer:str,
|
||||
has_server:bool,
|
||||
is_public:bool,
|
||||
has_update:bool,
|
||||
installed: bool
|
||||
):
|
||||
self.uid = uid
|
||||
self.name = name
|
||||
self.folder_name = folder_name
|
||||
@ -59,22 +72,31 @@ class AppInfo:
|
||||
self.version = version
|
||||
self.model_name = model_name
|
||||
self.disclaimer = disclaimer
|
||||
self.has_server = has_server
|
||||
self.has_update = has_update
|
||||
self.is_public = is_public
|
||||
self.installed = installed
|
||||
|
||||
@router.get("/apps")
|
||||
async def list_apps():
|
||||
apps = []
|
||||
apps_zoo_path = lollmsElfServer.lollms_paths.apps_zoo_path
|
||||
|
||||
REPO_DIR = lollmsElfServer.lollms_paths.personal_path/"apps_zoo_repo"
|
||||
if REPO_DIR.exists():
|
||||
remote_apps = [a.stem for a in REPO_DIR.iterdir()]
|
||||
else:
|
||||
remote_apps = []
|
||||
for app_name in apps_zoo_path.iterdir():
|
||||
if app_name.is_dir():
|
||||
icon_path = app_name / "icon.png"
|
||||
description_path = app_name / "description.yaml"
|
||||
description = ""
|
||||
author = ""
|
||||
version = ""
|
||||
current_version = ""
|
||||
model_name = ""
|
||||
disclaimer = ""
|
||||
has_server = False
|
||||
is_public = app_name.stem in remote_apps
|
||||
|
||||
if description_path.exists():
|
||||
with open(description_path, 'r') as file:
|
||||
@ -83,13 +105,29 @@ async def list_apps():
|
||||
category = data.get('category', 'generic')
|
||||
description = data.get('description', '')
|
||||
author = data.get('author', '')
|
||||
version = data.get('version', '')
|
||||
current_version = data.get('version', '')
|
||||
model_name = data.get('model_name', '')
|
||||
disclaimer = data.get('disclaimer', 'No disclaimer provided.')
|
||||
has_server = data.get('has_server', False)
|
||||
installed = True
|
||||
else:
|
||||
installed = False
|
||||
|
||||
|
||||
if is_public:
|
||||
try:
|
||||
with (REPO_DIR / app_name / "description.yaml").open("r") as file:
|
||||
# Parse the YAML content
|
||||
yaml_content = yaml.safe_load(file)
|
||||
repo_version = yaml_content.get("version", "0")
|
||||
|
||||
# Compare versions using packaging.version
|
||||
has_update = version.parse(str(repo_version)) > version.parse(str(current_version))
|
||||
except (yaml.YAMLError, FileNotFoundError) as e:
|
||||
print(f"Error reading or parsing YAML file: {e}")
|
||||
has_update = False
|
||||
else:
|
||||
has_update = False
|
||||
|
||||
if icon_path.exists():
|
||||
uid = str(uuid.uuid4())
|
||||
apps.append(AppInfo(
|
||||
@ -100,9 +138,12 @@ async def list_apps():
|
||||
category=category,
|
||||
description=description,
|
||||
author=author,
|
||||
version=version,
|
||||
version=current_version,
|
||||
model_name=model_name,
|
||||
disclaimer=disclaimer,
|
||||
has_server=has_server,
|
||||
is_public=is_public,
|
||||
has_update=has_update,
|
||||
installed=installed
|
||||
))
|
||||
|
||||
@ -197,13 +238,6 @@ async def download_app(input_data: AppNameInput):
|
||||
headers={"Content-Disposition": f"attachment; filename={app_name}.zip"}
|
||||
)
|
||||
|
||||
import os
|
||||
import yaml
|
||||
from fastapi import FastAPI, File, UploadFile, HTTPException
|
||||
from fastapi.responses import JSONResponse
|
||||
import zipfile
|
||||
import shutil
|
||||
|
||||
@router.post("/upload_app")
|
||||
async def upload_app(client_id: str, file: UploadFile = File(...)):
|
||||
check_access(lollmsElfServer, client_id)
|
||||
@ -352,6 +386,9 @@ def load_apps_data():
|
||||
version=description_data.get('version', ''),
|
||||
model_name=description_data.get('model_name', ''),
|
||||
disclaimer=description_data.get('disclaimer', 'No disclaimer provided.'),
|
||||
has_server=description_data.get('has_server', False),
|
||||
is_public=True,
|
||||
has_update=False,
|
||||
installed=True
|
||||
))
|
||||
return apps
|
||||
@ -416,9 +453,26 @@ async def fetch_github_apps():
|
||||
apps = load_apps_data()
|
||||
return {"apps": apps}
|
||||
|
||||
@router.get("/apps/{app_name}/icon")
|
||||
async def get_app_icon(app_name: str):
|
||||
icon_path = lollmsElfServer.lollms_paths.apps_zoo_path / app_name / "icon.png"
|
||||
if not icon_path.exists():
|
||||
raise HTTPException(status_code=404, detail="Icon not found")
|
||||
return FileResponse(icon_path)
|
||||
def run_server(app_path: Path):
|
||||
server_script = app_path / "server.py"
|
||||
if server_script.exists():
|
||||
subprocess.Popen(["python", str(server_script)], cwd=str(app_path))
|
||||
else:
|
||||
print(f"Server script not found for app: {app_path.name}")
|
||||
|
||||
@router.post("/apps/start_server")
|
||||
async def start_app_server(request: OpenFolderRequest):
|
||||
check_access(lollmsElfServer, request.client_id)
|
||||
app_path = lollmsElfServer.lollms_paths.apps_zoo_path / request.app_name
|
||||
|
||||
if not app_path.exists():
|
||||
raise HTTPException(status_code=404, detail="App not found")
|
||||
|
||||
server_script = app_path / "server.py"
|
||||
if not server_script.exists():
|
||||
raise HTTPException(status_code=404, detail="Server script not found for this app")
|
||||
|
||||
# Start the server in the background
|
||||
background_tasks.add_task(run_server, app_path)
|
||||
|
||||
return {"status": "success", "message": f"Server for {app_name} is starting"}
|
@ -35,4 +35,4 @@ scrapemaster
|
||||
|
||||
aiofiles
|
||||
python-multipart
|
||||
zipfile36
|
||||
zipfile36
|
||||
|
8
web/dist/assets/index-22501ef4.css
vendored
8
web/dist/assets/index-22501ef4.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
8
web/dist/assets/index-bfc4ff0e.css
vendored
Normal file
8
web/dist/assets/index-bfc4ff0e.css
vendored
Normal file
File diff suppressed because one or more lines are too long
4
web/dist/index.html
vendored
4
web/dist/index.html
vendored
@ -6,8 +6,8 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"></script>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>LoLLMS WebUI</title>
|
||||
<script type="module" crossorigin src="/assets/index-c846d59c.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-22501ef4.css">
|
||||
<script type="module" crossorigin src="/assets/index-7542a266.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-bfc4ff0e.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
@ -50,79 +50,101 @@
|
||||
<span class="text-xl text-gray-700 font-semibold">Loading...</span>
|
||||
</div>
|
||||
<div v-for="category in categories" :key="category" class="mb-12">
|
||||
<h2 class="text-3xl font-bold mb-6 text-gray-800">{{ category }}</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<div
|
||||
v-for="app in filteredApps.filter(a => a.category === category)"
|
||||
:key="app.uid"
|
||||
class="app-card bg-white border rounded-xl shadow-lg p-6 hover:shadow-xl transition duration-300 ease-in-out flex flex-col h-full"
|
||||
>
|
||||
<div class="flex-grow">
|
||||
<div class="flex items-center mb-4">
|
||||
<img :src="app.icon" alt="App Icon" class="w-16 h-16 rounded-full border border-gray-300 mr-4" />
|
||||
<div>
|
||||
<h3 class="font-bold text-xl text-gray-800">{{ app.name }}</h3>
|
||||
<p class="text-sm text-gray-600">Author: {{ app.author }}</p>
|
||||
<p class="text-sm text-gray-600">Version: {{ app.version }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<h4 class="font-semibold mb-1 text-gray-700">Description:</h4>
|
||||
<p class="text-sm text-gray-600 h-20 overflow-y-auto">{{ app.description }}</p>
|
||||
</div>
|
||||
|
||||
<p class="text-sm text-gray-600 mb-2">AI Model: {{ app.model_name }}</p>
|
||||
|
||||
<div v-if="app.disclaimer && app.disclaimer.trim() !== ''" class="mb-4">
|
||||
<h4 class="font-semibold mb-1 text-gray-700">Disclaimer:</h4>
|
||||
<p class="text-xs text-gray-500 italic h-16 overflow-y-auto">{{ app.disclaimer }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-auto pt-4 border-t">
|
||||
<div class="flex justify-between">
|
||||
<button v-if="app.installed" @click="uninstallApp(app.folder_name)" class="text-red-500 hover:text-red-600 transition duration-300 ease-in-out" title="Uninstall">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
||||
</svg>
|
||||
</button>
|
||||
<button v-else-if="app.existsInFolder" @click="deleteApp(app.name)" class="text-yellow-500 hover:text-yellow-600 transition duration-300 ease-in-out" title="Delete">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
||||
</svg>
|
||||
</button>
|
||||
<button v-else @click="installApp(app.folder_name)" class="text-blue-500 hover:text-blue-600 transition duration-300 ease-in-out" title="Install">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
|
||||
</svg>
|
||||
</button>
|
||||
<button v-if="app.installed" @click="editApp(app)" class="text-purple-500 hover:text-purple-600 transition duration-300 ease-in-out" title="Edit">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
|
||||
</svg>
|
||||
</button>
|
||||
<button @click="downloadApp(app.folder_name)" class="text-green-500 hover:text-green-600 transition duration-300 ease-in-out" title="Download">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
|
||||
</svg>
|
||||
</button>
|
||||
<button @click="handleAppClick(app)" class="text-gray-500 hover:text-gray-600 transition duration-300 ease-in-out" title="View">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
|
||||
</svg>
|
||||
</button>
|
||||
<button @click="openApp(app)" class="text-indigo-500 hover:text-indigo-600 transition duration-300 ease-in-out" title="Open">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<h2 class="text-3xl font-bold mb-6 text-gray-800">{{ category }}</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
<div
|
||||
v-for="app in filteredApps.filter(a => a.category === category)"
|
||||
:key="app.uid"
|
||||
class="app-card bg-white border rounded-xl shadow-lg p-6 hover:shadow-xl transition duration-300 ease-in-out flex flex-col h-full"
|
||||
>
|
||||
<div class="flex-grow">
|
||||
<div class="flex items-center mb-4">
|
||||
<img :src="app.icon" alt="App Icon" class="w-16 h-16 rounded-full border border-gray-300 mr-4" />
|
||||
<div>
|
||||
<h3 class="font-bold text-xl text-gray-800">{{ app.name }}</h3>
|
||||
<p class="text-sm text-gray-600">Author: {{ app.author }}</p>
|
||||
<p class="text-sm text-gray-600">Version: {{ app.version }}</p>
|
||||
<!-- New section for app visibility -->
|
||||
<p class="text-sm" :class="app.is_public ? 'text-green-600' : 'text-orange-600'">
|
||||
{{ app.is_public ? 'Public App' : 'Local App' }}
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<h4 class="font-semibold mb-1 text-gray-700">Description:</h4>
|
||||
<p class="text-sm text-gray-600 h-20 overflow-y-auto">{{ app.description }}</p>
|
||||
</div>
|
||||
|
||||
<p class="text-sm text-gray-600 mb-2">AI Model: {{ app.model_name }}</p>
|
||||
|
||||
<div v-if="app.disclaimer && app.disclaimer.trim() !== ''" class="mb-4">
|
||||
<h4 class="font-semibold mb-1 text-gray-700">Disclaimer:</h4>
|
||||
<p class="text-xs text-gray-500 italic h-16 overflow-y-auto">{{ app.disclaimer }}</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mt-auto pt-4 border-t">
|
||||
<div class="flex justify-between items-center flex-wrap">
|
||||
<button v-if="app.installed" @click="uninstallApp(app.folder_name)" class="text-red-500 hover:text-red-600 transition duration-300 ease-in-out" title="Uninstall">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
||||
</svg>
|
||||
</button>
|
||||
<button v-else-if="app.existsInFolder" @click="deleteApp(app.name)" class="text-yellow-500 hover:text-yellow-600 transition duration-300 ease-in-out" title="Delete">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
|
||||
</svg>
|
||||
</button>
|
||||
<button v-else @click="installApp(app.folder_name)" class="text-blue-500 hover:text-blue-600 transition duration-300 ease-in-out" title="Install">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
|
||||
</svg>
|
||||
</button>
|
||||
<button v-if="app.installed" @click="editApp(app)" class="text-purple-500 hover:text-purple-600 transition duration-300 ease-in-out" title="Edit">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
|
||||
</svg>
|
||||
</button>
|
||||
<button @click="downloadApp(app.folder_name)" class="text-green-500 hover:text-green-600 transition duration-300 ease-in-out" title="Download">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
|
||||
</svg>
|
||||
</button>
|
||||
<button @click="handleAppClick(app)" class="text-gray-500 hover:text-gray-600 transition duration-300 ease-in-out" title="View">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
|
||||
</svg>
|
||||
</button>
|
||||
<button @click="openApp(app)" class="text-indigo-500 hover:text-indigo-600 transition duration-300 ease-in-out" title="Open">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- New button for starting the server -->
|
||||
<button v-if="app.has_server && app.installed" @click="startServer(app.folder_name)" class="text-teal-500 hover:text-teal-600 transition duration-300 ease-in-out" title="Start Server">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M12 5l7 7-7 7" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<!-- New button for updating the app -->
|
||||
<button v-if="app.has_update" @click="updateApp(app.folder_name)" class="relative text-yellow-500 hover:text-yellow-600 transition duration-300 ease-in-out animate-pulse" title="Update Available">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
<span class="absolute top-0 right-0 inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-red-100 transform translate-x-1/2 -translate-y-1/2 bg-red-600 rounded-full">!</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div v-if="selectedApp" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
|
||||
<div class="bg-white rounded-lg p-6 w-11/12 h-5/6 flex flex-col">
|
||||
@ -185,7 +207,35 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
triggerFileInput() {
|
||||
startServer(appName) {
|
||||
const payload = {
|
||||
client_id: this.$store.state.client_id, // Assuming you have a clientId property in your component
|
||||
app_name: appName
|
||||
};
|
||||
|
||||
axios.post(`/apps/start_server`, payload)
|
||||
.then(response => {
|
||||
// Handle successful server start
|
||||
console.log('Server start initiated:', response.data.message);
|
||||
// You might want to show a notification to the user here
|
||||
this.$notify({
|
||||
type: 'success',
|
||||
title: 'Server Starting',
|
||||
text: response.data.message
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
// Handle error
|
||||
console.error('Error starting server:', error);
|
||||
// Show an error notification
|
||||
this.$notify({
|
||||
type: 'error',
|
||||
title: 'Server Start Failed',
|
||||
text: error.response?.data?.detail || 'An error occurred while starting the server'
|
||||
});
|
||||
});
|
||||
},
|
||||
triggerFileInput() {
|
||||
this.$refs.fileInput.click();
|
||||
},
|
||||
onFileSelected(event) {
|
||||
|
Loading…
Reference in New Issue
Block a user