@gramercytech/gx-toolkit
Version:
Dev tools for create platform plugins
525 lines (455 loc) • 11.5 kB
HTML
<html>
<head>
<meta charset="utf-8">
<style>
:root {
--main-bg: #f8f9fa;
--header-bg: #2563eb;
--card-bg: #ffffff;
--border-color: #e5e7eb;
--text-primary: #1f2937;
--text-secondary: #6b7280;
--success-color: #10b981;
--error-color: #ef4444;
--warning-color: #f59e0b;
--shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
font-size: 14px;
line-height: 1.5;
color: var(--text-primary);
background: var(--main-bg);
width: 420px;
min-height: 500px;
}
.header {
background: linear-gradient(135deg, var(--header-bg) 0%, #1d4ed8 100%);
color: white;
padding: 20px;
text-align: center;
box-shadow: var(--shadow);
}
.header h1 {
font-size: 18px;
font-weight: 600;
margin: 0 0 8px 0;
}
.header .subtitle {
font-size: 12px;
opacity: 0.9;
font-weight: 400;
}
.main-container {
padding: 20px;
}
/* Main Toggle Section */
.main-toggle {
background: var(--card-bg);
border-radius: 12px;
box-shadow: var(--shadow);
overflow: hidden;
margin-bottom: 20px;
}
.toggle-header {
padding: 16px 20px;
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
}
.toggle-title {
font-weight: 600;
font-size: 15px;
}
.master-toggle {
position: relative;
width: 52px;
height: 28px;
}
.master-toggle input {
opacity: 0;
width: 0;
height: 0;
}
.master-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #cbd5e1;
border-radius: 28px;
transition: all 0.3s ease;
}
.master-slider:before {
position: absolute;
content: "";
height: 22px;
width: 22px;
left: 3px;
bottom: 3px;
background-color: white;
border-radius: 50%;
transition: all 0.3s ease;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
.master-toggle input:checked + .master-slider {
background-color: var(--success-color);
}
.master-toggle input:checked + .master-slider:before {
transform: translateX(24px);
}
.status-info {
padding: 12px 20px;
background: #f1f5f9;
font-size: 13px;
color: var(--text-secondary);
}
/* Rule Cards */
.rule-container {
background: var(--card-bg);
border-radius: 12px;
box-shadow: var(--shadow);
overflow: hidden;
margin-bottom: 16px;
}
.rule-header {
padding: 16px 20px;
border-bottom: 1px solid var(--border-color);
display: flex;
align-items: center;
justify-content: space-between;
background: #fafbfc;
}
.rule-title {
font-weight: 600;
font-size: 14px;
color: var(--text-primary);
}
.rule-subtitle {
font-size: 12px;
color: var(--text-secondary);
margin-top: 2px;
}
.rule-toggle {
position: relative;
width: 44px;
height: 24px;
}
.rule-toggle input {
opacity: 0;
width: 0;
height: 0;
}
.rule-slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #cbd5e1;
border-radius: 24px;
transition: all 0.3s ease;
}
.rule-slider:before {
position: absolute;
content: "";
height: 18px;
width: 18px;
left: 3px;
bottom: 3px;
background-color: white;
border-radius: 50%;
transition: all 0.3s ease;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
.rule-toggle input:checked + .rule-slider {
background-color: var(--success-color);
}
.rule-toggle input:checked + .rule-slider:before {
transform: translateX(20px);
}
.rule-content {
padding: 20px;
}
/* Form Fields */
.form-group {
margin-bottom: 16px;
}
.form-group:last-child {
margin-bottom: 0;
}
.form-group label {
display: block;
font-weight: 500;
margin-bottom: 6px;
font-size: 13px;
color: var(--text-primary);
}
.form-group input,
.form-group textarea {
width: 100%;
padding: 10px 12px;
border: 1px solid var(--border-color);
border-radius: 8px;
font-size: 13px;
transition: all 0.2s ease;
background: white;
}
.form-group input:focus,
.form-group textarea:focus {
outline: none;
border-color: var(--header-bg);
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}
.form-group textarea {
resize: vertical;
min-height: 65px;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
}
/* Checkbox */
.checkbox-group {
display: flex;
align-items: center;
margin-bottom: 16px;
}
.checkbox-group input[type="checkbox"] {
width: auto;
margin-right: 8px;
cursor: pointer;
}
.checkbox-group label {
margin-bottom: 0;
cursor: pointer;
font-size: 13px;
}
/* Action Buttons */
.action-buttons {
display: flex;
gap: 8px;
margin-top: 20px;
}
.btn {
flex: 1;
padding: 10px 16px;
border: none;
border-radius: 8px;
font-size: 13px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
text-align: center;
}
.btn-primary {
background: var(--header-bg);
color: white;
}
.btn-primary:hover {
background: #1d4ed8;
transform: translateY(-1px);
box-shadow: var(--shadow-lg);
}
.btn-secondary {
background: #f3f4f6;
color: var(--text-primary);
border: 1px solid var(--border-color);
}
.btn-secondary:hover {
background: #e5e7eb;
transform: translateY(-1px);
}
.btn:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none ;
}
/* Status Messages */
.status-message {
padding: 12px 16px;
border-radius: 8px;
margin-bottom: 16px;
font-size: 13px;
font-weight: 500;
}
.status-success {
background: #ecfdf5;
color: #065f46;
border: 1px solid #a7f3d0;
}
.status-error {
background: #fef2f2;
color: #991b1b;
border: 1px solid #fca5a5;
}
/* Hidden class */
.hidden {
display: none ;
}
/* Disabled state for rule containers */
.rule-container.disabled {
opacity: 0.6;
}
.rule-container.disabled .rule-content {
pointer-events: none;
}
/* Pattern info */
.pattern-info {
font-size: 11px;
color: var(--text-secondary);
margin-top: 4px;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
}
/* Advanced Settings */
.advanced-settings {
background: var(--card-bg);
border-radius: 12px;
box-shadow: var(--shadow);
overflow: hidden;
margin-top: 20px;
}
.advanced-header {
padding: 16px 20px;
background: #fafbfc;
border-bottom: 1px solid var(--border-color);
cursor: pointer;
display: flex;
align-items: center;
justify-content: space-between;
}
.advanced-header:hover {
background: #f1f5f9;
}
.advanced-title {
font-weight: 600;
font-size: 14px;
}
.advanced-toggle {
font-size: 12px;
color: var(--text-secondary);
}
.advanced-content {
padding: 20px;
}
</style>
</head>
<body>
<div class="header">
<h1>JavaScript Proxy</h1>
<div class="subtitle">Intercept & redirect web requests</div>
</div>
<div class="main-container">
<!-- Status Messages -->
<div id="statusMessage" class="status-message hidden"></div>
<!-- Main Toggle -->
<div class="main-toggle">
<div class="toggle-header">
<div class="toggle-title">Proxy Extension</div>
<label class="master-toggle">
<input type="checkbox" id="masterToggle">
<span class="master-slider"></span>
</label>
</div>
<div class="status-info" id="statusInfo">
Extension is currently disabled
</div>
</div>
<!-- JavaScript Rule -->
<div class="rule-container" id="jsRuleContainer">
<div class="rule-header">
<div>
<div class="rule-title">JavaScript Files (.js)</div>
<div class="rule-subtitle">Redirect JavaScript files to development server</div>
</div>
<label class="rule-toggle">
<input type="checkbox" id="jsRuleToggle">
<span class="rule-slider"></span>
</label>
</div>
<div class="rule-content">
<div class="form-group">
<label for="jsRedirectUrl">Redirect URL:</label>
<input type="url" id="jsRedirectUrl" placeholder="https://localhost:3060/src/Plugin.vue">
</div>
<div class="checkbox-group">
<input type="checkbox" id="jsUseCustomPattern">
<label for="jsUseCustomPattern">Use custom URL pattern</label>
</div>
<div class="form-group" id="jsPatternGroup">
<label for="jsPattern">URL Pattern (RegEx):</label>
<textarea id="jsPattern" placeholder="uploads\/plugin-version\/\d+\/file_name\/.*\.js(\?.*)?"></textarea>
<div class="pattern-info">Matches JavaScript files in plugin uploads</div>
</div>
</div>
</div>
<!-- CSS Rule -->
<div class="rule-container" id="cssRuleContainer">
<div class="rule-header">
<div>
<div class="rule-title">CSS Files (.css)</div>
<div class="rule-subtitle">Handle CSS files with redirect or blank return</div>
</div>
<label class="rule-toggle">
<input type="checkbox" id="cssRuleToggle">
<span class="rule-slider"></span>
</label>
</div>
<div class="rule-content">
<div class="checkbox-group">
<input type="checkbox" id="cssReturnBlank">
<label for="cssReturnBlank">Return blank CSS document instead of redirecting</label>
</div>
<div class="form-group" id="cssRedirectGroup">
<label for="cssRedirectUrl">Redirect URL:</label>
<input type="url" id="cssRedirectUrl" placeholder="https://localhost:3060/src/styles.css">
</div>
<div class="checkbox-group">
<input type="checkbox" id="cssUseCustomPattern">
<label for="cssUseCustomPattern">Use custom URL pattern</label>
</div>
<div class="form-group" id="cssPatternGroup">
<label for="cssPattern">URL Pattern (RegEx):</label>
<textarea id="cssPattern" placeholder="uploads\/plugin-version\/\d+\/style_file_name\/.*\.css(\?.*)?"></textarea>
<div class="pattern-info">Matches CSS files in plugin uploads</div>
</div>
</div>
</div>
<!-- Advanced Settings -->
<div class="advanced-settings">
<div class="advanced-header" id="advancedHeader">
<div class="advanced-title">Advanced Settings</div>
<div class="advanced-toggle" id="advancedToggle">Show ▼</div>
</div>
<div class="advanced-content hidden" id="advancedContent">
<div class="checkbox-group">
<input type="checkbox" id="maskingMode">
<label for="maskingMode">URL Masking Mode (experimental)</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="clearCacheOnEnable">
<label for="clearCacheOnEnable">Clear cache when enabling proxy</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="disableCacheForRedirects">
<label for="disableCacheForRedirects">Disable cache for redirected requests</label>
</div>
</div>
</div>
<!-- Action Buttons -->
<div class="action-buttons">
<button class="btn btn-secondary" id="clearCacheBtn">Clear Cache</button>
<button class="btn btn-primary" id="saveBtn">Save Changes</button>
</div>
</div>
<script src="popup.js"></script>
</body>
</html>