parapet-rails 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +48 -0
- data/Rakefile +7 -0
- data/app/assets/config/parapet/grammar-registry.json +52 -0
- data/app/assets/images/parapet/icons/activities/component-inspector.svg +4 -0
- data/app/assets/images/parapet/icons/activities/coverage-heatmap.svg +3 -0
- data/app/assets/images/parapet/icons/activities/discovery-sidebar.svg +3 -0
- data/app/assets/images/parapet/icons/activities/environment-toggles.svg +4 -0
- data/app/assets/images/parapet/icons/activities/failure-inspector.svg +5 -0
- data/app/assets/images/parapet/icons/activities/flaky-history.svg +3 -0
- data/app/assets/images/parapet/icons/activities/flight-recorder.svg +5 -0
- data/app/assets/images/parapet/icons/activities/health-graph.svg +3 -0
- data/app/assets/images/parapet/icons/activities/injection-engine.svg +3 -0
- data/app/assets/images/parapet/icons/activities/live-sql-stream.svg +5 -0
- data/app/assets/images/parapet/icons/activities/live-web-preview.svg +4 -0
- data/app/assets/images/parapet/icons/activities/monaco-editor.svg +5 -0
- data/app/assets/images/parapet/icons/activities/progress-area.svg +3 -0
- data/app/assets/images/parapet/icons/activities/registry-metadata.svg +5 -0
- data/app/assets/images/parapet/icons/activities/seed-inspector.svg +4 -0
- data/app/assets/images/parapet/icons/activities/slow-test-bottlenecks.svg +4 -0
- data/app/assets/images/parapet/icons/activities/smart-search.svg +4 -0
- data/app/assets/images/parapet/icons/activities/snippet-library.svg +4 -0
- data/app/assets/images/parapet/icons/activities/terminal.svg +4 -0
- data/app/assets/images/parapet/icons/activities/unified-schema-view.svg +4 -0
- data/app/assets/images/parapet/icons/activities/visual-comparison.svg +3 -0
- data/app/assets/images/parapet/icons/activities/visual-summary-bar.svg +5 -0
- data/app/assets/images/parapet/icons/nav/ideas.svg +4 -0
- data/app/assets/images/parapet/icons/nav/languages.svg +8 -0
- data/app/assets/images/parapet/icons/nav/profile.svg +4 -0
- data/app/assets/images/parapet/icons/nav/pulse.svg +7 -0
- data/app/assets/images/parapet/icons/nav/settings.svg +4 -0
- data/app/assets/images/parapet/icons/nav/state.svg +5 -0
- data/app/assets/images/parapet/icons/nav/styles.svg +7 -0
- data/app/assets/images/parapet/icons/nav/tests.svg +4 -0
- data/app/assets/images/parapet/icons/nav/traffic.svg +12 -0
- data/app/assets/javascripts/parapet/activity-card.js +439 -0
- data/app/assets/javascripts/parapet/activity-cards.js +291 -0
- data/app/assets/javascripts/parapet/activity-registry.js +181 -0
- data/app/assets/javascripts/parapet/activity-toggles.js +76 -0
- data/app/assets/javascripts/parapet/application.js +37 -0
- data/app/assets/javascripts/parapet/card-failure-inspector.js +134 -0
- data/app/assets/javascripts/parapet/card-file-editor.js +1722 -0
- data/app/assets/javascripts/parapet/card-progress-area.js +297 -0
- data/app/assets/javascripts/parapet/card-smart-search.js +114 -0
- data/app/assets/javascripts/parapet/card-snippet-library.js +251 -0
- data/app/assets/javascripts/parapet/explorer-resizer.js +92 -0
- data/app/assets/javascripts/parapet/parapet_qss.js +342 -0
- data/app/assets/javascripts/parapet/proficiency-filter.js +53 -0
- data/app/assets/javascripts/parapet/sidebar-resizer.js +197 -0
- data/app/assets/javascripts/parapet/styles-workbench.js +819 -0
- data/app/assets/javascripts/parapet/tree-logic.js +320 -0
- data/app/assets/stylesheets/parapet/_qss_variables.scss +122 -0
- data/app/assets/stylesheets/parapet/parapet_qss.scss +69 -0
- data/app/assets/stylesheets/parapet/qss_application.css +260940 -0
- data/app/assets/stylesheets/parapet/qss_application.css.map +1 -0
- data/app/assets/stylesheets/parapet/qss_application.scss +5 -0
- data/app/assets/stylesheets/parapet/qss_workspace.scss +209 -0
- data/app/assets/stylesheets/parapet/sample.qss +22 -0
- data/app/controllers/parapet/application_controller.rb +54 -0
- data/app/controllers/parapet/base_controller.rb +18 -0
- data/app/controllers/parapet/build_suite/dashboard_controller.rb +10 -0
- data/app/controllers/parapet/css_suite/compiler_controller.rb +95 -0
- data/app/controllers/parapet/css_suite/dashboard_controller.rb +10 -0
- data/app/controllers/parapet/css_suite/preview_controller.rb +46 -0
- data/app/controllers/parapet/dashboard_controller.rb +8 -0
- data/app/controllers/parapet/drafts_controller.rb +30 -0
- data/app/controllers/parapet/explorers_controller.rb +53 -0
- data/app/controllers/parapet/files_controller.rb +208 -0
- data/app/controllers/parapet/footers_controller.rb +24 -0
- data/app/controllers/parapet/intentions_suite/dashboard_controller.rb +10 -0
- data/app/controllers/parapet/landing_controller.rb +14 -0
- data/app/controllers/parapet/monitor_suite/dashboard_controller.rb +10 -0
- data/app/controllers/parapet/pm_suite/publish_controller.rb +16 -0
- data/app/controllers/parapet/polyglot_suite/dashboard_controller.rb +10 -0
- data/app/controllers/parapet/runner_controller.rb +34 -0
- data/app/controllers/parapet/sessions_controller.rb +35 -0
- data/app/controllers/parapet/signal_suite/dashboard_controller.rb +10 -0
- data/app/controllers/parapet/test_suite/dashboard_controller.rb +10 -0
- data/app/controllers/parapet/widgets_controller.rb +33 -0
- data/app/helpers/parapet/application_helper.rb +23 -0
- data/app/helpers/parapet/icon_helper.rb +57 -0
- data/app/jobs/parapet/application_job.rb +4 -0
- data/app/mailers/parapet/application_mailer.rb +6 -0
- data/app/models/parapet/activity.rb +14 -0
- data/app/models/parapet/application_record.rb +5 -0
- data/app/models/parapet/current.rb +6 -0
- data/app/models/parapet/draft_recovery.rb +9 -0
- data/app/models/parapet/internal_record.rb +34 -0
- data/app/models/parapet/run_history.rb +22 -0
- data/app/models/parapet/runtime_setting.rb +8 -0
- data/app/models/parapet/session.rb +7 -0
- data/app/models/parapet/suite_assignment.rb +30 -0
- data/app/models/parapet/user.rb +12 -0
- data/app/services/parapet/activity_phrase_renderer.rb +35 -0
- data/app/services/parapet/activity_writer.rb +26 -0
- data/app/services/parapet/authorization.rb +198 -0
- data/app/services/parapet/consistency_auditor.rb +58 -0
- data/app/services/parapet/directory_scanner.rb +159 -0
- data/app/services/parapet/draft_recovery_store.rb +18 -0
- data/app/services/parapet/explorer_manager.rb +402 -0
- data/app/services/parapet/file_save_service.rb +21 -0
- data/app/services/parapet/git_side_ref_committer.rb +50 -0
- data/app/services/parapet/noun_discovery.rb +26 -0
- data/app/services/parapet/publish_gate.rb +83 -0
- data/app/services/parapet/test_runner.rb +178 -0
- data/app/views/layouts/parapet/application.html.erb +83 -0
- data/app/views/layouts/parapet/landing.html.erb +19 -0
- data/app/views/parapet/activities/_ai_error_explainer.html.erb +33 -0
- data/app/views/parapet/activities/_ai_explainer_widget.html.erb +20 -0
- data/app/views/parapet/activities/_calendar_widget.html.erb +31 -0
- data/app/views/parapet/activities/_code_snippets_widget.html.erb +22 -0
- data/app/views/parapet/activities/_coverage_explorer.html.erb +1 -0
- data/app/views/parapet/activities/_dropdown_test.html.erb +20 -0
- data/app/views/parapet/activities/_explorer_node.html.erb +102 -0
- data/app/views/parapet/activities/_explorer_tree.html.erb +16 -0
- data/app/views/parapet/activities/_file_editor.html.erb +183 -0
- data/app/views/parapet/activities/_file_explorer.html.erb +23 -0
- data/app/views/parapet/activities/_fix_suggestions_widget.html.erb +13 -0
- data/app/views/parapet/activities/_generic.html.erb +6 -0
- data/app/views/parapet/activities/_live_preview.html.erb +13 -0
- data/app/views/parapet/activities/_perspective_filters.html.erb +36 -0
- data/app/views/parapet/activities/_progress_area.html.erb +37 -0
- data/app/views/parapet/activities/_project_explorer.html.erb +1 -0
- data/app/views/parapet/activities/_registry_explorer.html.erb +1 -0
- data/app/views/parapet/activities/_run_history.html.erb +2 -0
- data/app/views/parapet/activities/_smart_search.html.erb +11 -0
- data/app/views/parapet/activities/file_explorer/_perspective_scripts.html.erb +58 -0
- data/app/views/parapet/activities/file_explorer/_perspectives.html.erb +0 -0
- data/app/views/parapet/activities/file_explorer/_viewport_scripts.html.erb +33 -0
- data/app/views/parapet/css_suite/_workbench.html.erb +51 -0
- data/app/views/parapet/dashboards/index.html.erb +113 -0
- data/app/views/parapet/debug_panel.html.erb +79 -0
- data/app/views/parapet/debug_panel_tailwind.html.erb +98 -0
- data/app/views/parapet/erb_patch_test.html.erb +5 -0
- data/app/views/parapet/explorers/show.html.erb +1 -0
- data/app/views/parapet/git_viewer.html.erb +62 -0
- data/app/views/parapet/git_viewer_after.html.erb +14 -0
- data/app/views/parapet/git_viewer_before.html.erb +14 -0
- data/app/views/parapet/git_viewer_governed.html.erb +88 -0
- data/app/views/parapet/git_viewer_governed_after.html.erb +36 -0
- data/app/views/parapet/git_viewer_governed_before.html.erb +36 -0
- data/app/views/parapet/git_viewer_tailwind.html.erb +88 -0
- data/app/views/parapet/git_viewer_thin_wrapper.html.erb +85 -0
- data/app/views/parapet/hierarchical_layout_test.html.erb +85 -0
- data/app/views/parapet/hybrid_stress_test.html.erb +25 -0
- data/app/views/parapet/index.html.erb +35 -0
- data/app/views/parapet/mutation_stress_test.html.erb +82 -0
- data/app/views/parapet/recursive_anchoring_test.html.erb +66 -0
- data/app/views/parapet/sessions/new.html.erb +28 -0
- data/app/views/parapet/shared/_cad_inspector.html.erb +92 -0
- data/app/views/parapet/shared/_discovery_sidebar.html.erb +48 -0
- data/app/views/parapet/shared/_explorer_bar.html.erb +71 -0
- data/app/views/parapet/shared/_footer.html.erb +10 -0
- data/app/views/parapet/shared/_footer_ideas.html.erb +36 -0
- data/app/views/parapet/shared/_footer_languages.html.erb +33 -0
- data/app/views/parapet/shared/_footer_pulse.html.erb +33 -0
- data/app/views/parapet/shared/_footer_state.html.erb +33 -0
- data/app/views/parapet/shared/_footer_styles.html.erb +37 -0
- data/app/views/parapet/shared/_footer_tests.html.erb +39 -0
- data/app/views/parapet/shared/_footer_traffic.html.erb +45 -0
- data/app/views/parapet/shared/_global_nav.html.erb +55 -0
- data/app/views/parapet/shared/_head.html.erb +4 -0
- data/app/views/parapet/shared/_header.html.erb +20 -0
- data/app/views/parapet/shared/_object_inspector.html.erb +76 -0
- data/app/views/parapet/shared/_ribbon_header.html.erb +3 -0
- data/app/views/parapet/shared/_root_selector_modal.html.erb +15 -0
- data/app/views/parapet/shared/_tab_bar.html.erb +62 -0
- data/app/views/parapet/shared/activities_ribbon/_agent_group.html.erb +15 -0
- data/app/views/parapet/shared/activities_ribbon/_analysis_group.html.erb +15 -0
- data/app/views/parapet/shared/activities_ribbon/_architect_group.html.erb +21 -0
- data/app/views/parapet/shared/activities_ribbon/_explorer_group.html.erb +12 -0
- data/app/views/parapet/shared/activities_ribbon/_inspector_group.html.erb +15 -0
- data/app/views/parapet/shared/activities_ribbon/_proficiency_filter.html.erb +24 -0
- data/app/views/parapet/shared/activities_ribbon/_runner_group.html.erb +21 -0
- data/app/views/parapet/shared/activities_ribbon/_spatial_inspector_group.html.erb +18 -0
- data/app/views/parapet/shared/activities_ribbon/_studio_group.html.erb +18 -0
- data/app/views/parapet/shared/activities_ribbon/_stylist_group.html.erb +18 -0
- data/app/views/parapet/shared/explorers/_base.html.erb +107 -0
- data/app/views/parapet/shared/explorers/_css.html.erb +1 -0
- data/app/views/parapet/shared/explorers/_intentions.html.erb +1 -0
- data/app/views/parapet/shared/explorers/_project.html.erb +1 -0
- data/app/views/parapet/shared/explorers/_tests.html.erb +1 -0
- data/app/views/parapet/shared/head/_meta.html.erb +3 -0
- data/app/views/parapet/shared/head/_styles_activities.html.erb +152 -0
- data/app/views/parapet/shared/head/_styles_shared.html.erb +52 -0
- data/app/views/parapet/shared/head/_styles_workspace.html.erb +67 -0
- data/app/views/parapet/shared/ribbon_header/_diagnostic_controls.html.erb +17 -0
- data/app/views/parapet/shared/ribbon_header/_execution_controls.html.erb +28 -0
- data/app/views/parapet/shared/ribbon_header/_focus_search.html.erb +5 -0
- data/app/views/parapet/shared/root_selector/_header.html.erb +10 -0
- data/app/views/parapet/shared/root_selector/_path_input.html.erb +13 -0
- data/app/views/parapet/shared/root_selector/_quick_select.html.erb +20 -0
- data/app/views/parapet/shared/root_selector/_scripts.html.erb +61 -0
- data/app/views/parapet/shared/root_selector/_warning.html.erb +11 -0
- data/app/views/parapet/shared/widgets/_base.html.erb +6 -0
- data/app/views/parapet/shared/widgets/_css.html.erb +79 -0
- data/app/views/parapet/widgets/_explainer.html.erb +17 -0
- data/app/views/parapet/widgets/_hotkeys.html.erb +20 -0
- data/app/views/parapet/widgets/_search.html.erb +68 -0
- data/app/views/parapet/widgets/_spatial_inspector.html.erb +54 -0
- data/app/views/parapet/widgets/_widget-explainer.html.erb +17 -0
- data/app/views/parapet/widgets/_widget-hotkeys.html.erb +20 -0
- data/app/views/parapet/widgets/_widget-search.html.erb +68 -0
- data/app/views/parapet/widgets/_widget-snippets.html.erb +18 -0
- data/app/views/parapet/widgets/_widget-suggestions.html.erb +15 -0
- data/app/views/parapet/widgets/show.html.erb +3 -0
- data/app/views/shared/_footer.html.erb +0 -0
- data/config/parapet/qss_config.yml +117 -0
- data/config/parapet/qss_registry.yml +14 -0
- data/config/routes.rb +40 -0
- data/db/migrate/20260916035300_create_run_histories.rb +16 -0
- data/db/migrate/20261002000000_expand_run_histories_for_activity_tracking.rb +7 -0
- data/db/parapet_migrate/20260929184200_create_parapet_users.rb +12 -0
- data/db/parapet_migrate/20260929184300_create_parapet_sessions.rb +9 -0
- data/db/parapet_migrate/20260930000000_create_parapet_runtime_settings.rb +12 -0
- data/db/parapet_migrate/20260930000100_create_parapet_suite_assignments.rb +14 -0
- data/db/parapet_migrate/20261002000000_create_parapet_activities.rb +16 -0
- data/db/parapet_migrate/20261002000100_create_parapet_draft_recoveries.rb +13 -0
- data/db/parapet_schema.rb +64 -0
- data/db/schema.rb +21 -0
- data/db/schema.released.rb +0 -0
- data/lib/parapet/engine.rb +11 -0
- data/lib/parapet/environment_guard.rb +14 -0
- data/lib/parapet/version.rb +3 -0
- data/lib/parapet-rails.rb +1 -0
- data/lib/parapet.rb +59 -0
- data/lib/tasks/parapet_qss.rake +26 -0
- data/lib/tasks/parapet_tasks.rake +25 -0
- data/lib/tasks/randomize_explorer_health.rb +101 -0
- metadata +423 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
<template id="qss-tpl-file-editor">
|
|
2
|
+
<div id="pp-file-editor-shell" class="qss-flex qss-flex-col qss-w-full qss-h-full qss-text-left qss-overflow-hidden qss-border qss-border-slate-800 qss-min-h-0 qss-contain-layout">
|
|
3
|
+
<!-- Editor Viewport (Dynamic Panes) -->
|
|
4
|
+
<div id="pp-editor-viewport" class="qss-editor-viewport qss-flex-1 qss-flex qss-w-full qss-h-full qss-bg-[#1e1e1e] qss-overflow-hidden qss-min-h-0 qss-contain-layout"></div>
|
|
5
|
+
</div>
|
|
6
|
+
</template>
|
|
7
|
+
|
|
8
|
+
<template id="qss-tpl-editor-pane">
|
|
9
|
+
<div class="qss-editor-pane qss-flex-1 qss-flex qss-flex-col qss-w-full qss-h-full qss-overflow-hidden qss-transition-all qss-duration-200 qss-rounded-sm qss-opacity-100 qss-min-w-0 qss-contain-layout" data-qss-active="false" data-qss-linked="false">
|
|
10
|
+
<!-- Tab Bar -->
|
|
11
|
+
<div class="qss-editor-tab-bar qss-relative qss-flex qss-items-start qss-border-b qss-border-slate-800/60 qss-flex-shrink-0 qss-justify-between qss-h-[26]">
|
|
12
|
+
<div class="qss-flex qss-items-center qss-flex-1 qss-min-w-0 qss-overflow-hidden qss-relative">
|
|
13
|
+
<div class="qss-flex qss-items-center qss-flex-nowrap qss-editor-tab-strip qss-overflow-x-auto qss-custom-scrollbar-h no-scrollbar"></div>
|
|
14
|
+
|
|
15
|
+
<!-- Mini-Explorer Down Chevron -->
|
|
16
|
+
<div class="qss-relative qss-group/mini-explorer qss-flex-shrink-0">
|
|
17
|
+
<button class="qss-pane-action-btn qss-flex qss-items-center qss-justify-center qss-w-6 qss-h-full qss-text-slate-500 hover:qss-text-white qss-border-l qss-border-slate-800/40 qss-bg-[#111418]/20 qss-transition-colors" title="Open Buffers" data-action="mini-explorer">
|
|
18
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="qss-w-4 qss-h-4"><path d="m6 9 6 6 6-6"></path></svg>
|
|
19
|
+
</button>
|
|
20
|
+
<div id="pp-portal-mini-explorer-dropdown" class="qss-mini-explorer-dropdown qss-absolute qss-w-64 qss-bg-[#1a1d23] qss-border qss-border-slate-800 qss-rounded qss-shadow-2xl qss-z-[120] qss-hidden group-hover/mini-explorer:qss-block qss-pointer-events-auto" style="--dropdown-top: auto; --dropdown-left: auto;">
|
|
21
|
+
<div class="qss-p-2 qss-border-b qss-border-slate-800/50">
|
|
22
|
+
<input type="text" class="qss-w-full qss-bg-black/40 qss-border qss-border-slate-700 qss-rounded qss-px-2 qss-py-1 qss-text-[10px] qss-text-slate-300 focus:qss-outline-none focus:qss-border-indigo-500" placeholder="Search open buffers...">
|
|
23
|
+
</div>
|
|
24
|
+
<div class="qss-buffer-list qss-flex qss-flex-col qss-py-1 qss-max-h-64 qss-overflow-y-auto qss-custom-scrollbar"></div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<!-- Pane Status Overlay -->
|
|
30
|
+
<div class="qss-pane-status-container qss-absolute qss-right-0 qss-top-0 qss-h-full qss-overflow-hidden qss-pointer-events-none qss-flex qss-justify-end">
|
|
31
|
+
<div class="qss-pane-status-msg qss-h-full qss-text-white qss-text-[9px] qss-font-bold qss-px-3 qss-flex qss-items-center qss-translate-x-full">
|
|
32
|
+
<!-- Text injected by JS -->
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div class="qss-pane-toolbar qss-flex qss-items-center qss-px-1 qss-border-l qss-border-slate-800/40 qss-bg-[#111418]/20 qss-h-full">
|
|
37
|
+
<!-- Buttons targeted by JS for context -->
|
|
38
|
+
<button class="qss-pane-action-btn qss-flex qss-items-center qss-justify-center qss-w-6 qss-h-full qss-text-slate-500 hover:qss-text-indigo-400 hover:qss-bg-white/5 qss-transition-all" title="Run Current Test" data-action="run">
|
|
39
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="qss-w-3.5 qss-h-3.5"><circle cx="12" cy="12" r="10"></circle><polygon points="10 8 16 12 10 16 10 8"></polygon></svg>
|
|
40
|
+
</button>
|
|
41
|
+
<button class="qss-pane-action-btn qss-flex qss-items-center qss-justify-center qss-w-6 qss-h-full qss-text-slate-500 hover:qss-text-orange-400 hover:qss-bg-white/5 qss-transition-all" title="Toggle Code Help" data-action="toggle-snippets">
|
|
42
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="qss-w-3.5 qss-h-3.5"><path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .5 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"></path><path d="M9 18h6"></path><path d="M10 22h4"></path></svg>
|
|
43
|
+
</button>
|
|
44
|
+
<button class="qss-pane-action-btn qss-flex qss-items-center qss-justify-center qss-w-6 qss-h-full qss-text-slate-500 hover:qss-text-emerald-400 hover:qss-bg-white/5 qss-transition-all qss-hidden" title="Save File (Ctrl+S)" data-action="save">
|
|
45
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="qss-w-3.5 qss-h-3.5"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path><polyline points="17 21 17 13 7 13 7 21"></polyline><polyline points="7 3 7 8 15 8"></polyline></svg>
|
|
46
|
+
</button>
|
|
47
|
+
<button class="qss-pane-action-btn qss-flex qss-items-center qss-justify-center qss-w-6 qss-h-full qss-text-slate-500 hover:qss-text-indigo-400 hover:qss-bg-white/5 qss-transition-all" title="Add Split" data-action="split">
|
|
48
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="qss-w-3.5 qss-h-3.5"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><line x1="9" y1="3" x2="9" y2="21"></line></svg>
|
|
49
|
+
</button>
|
|
50
|
+
|
|
51
|
+
<div class="qss-w-px qss-h-3 qss-bg-slate-800/50 qss-mx-1"></div>
|
|
52
|
+
|
|
53
|
+
<div class="qss-relative qss-group/new-menu qss-h-full">
|
|
54
|
+
<button class="qss-pane-action-btn qss-flex qss-items-center qss-justify-center qss-w-6 qss-h-full qss-text-slate-500 hover:qss-text-white hover:qss-bg-white/5 qss-transition-all" title="New File" data-action="new-menu">
|
|
55
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="qss-w-4 qss-h-4"><path d="M5 12h14"></path><path d="M12 5v14"></path></svg>
|
|
56
|
+
</button>
|
|
57
|
+
<div id="pp-portal-new-menu-dropdown" class="qss-new-menu-dropdown qss-absolute qss-w-40 qss-bg-[#1a1d23] qss-border qss-border-slate-800 qss-rounded qss-shadow-2xl qss-z-[100] qss-hidden group-hover/new-menu:qss-block qss-pointer-events-auto" style="--dropdown-top: auto; --dropdown-left: auto;">
|
|
58
|
+
<div class="qss-template-list qss-flex qss-flex-col qss-py-1">
|
|
59
|
+
<!-- Populated in JS -->
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<div class="qss-relative qss-group/link-menu">
|
|
65
|
+
<button class="qss-pane-action-btn qss-link-btn qss-flex qss-items-center qss-justify-center qss-w-6 qss-h-full qss-text-slate-500 hover:qss-text-indigo-400 hover:qss-bg-white/5 qss-transition-all" title="Link/Unlink Mirror" data-action="toggle-link">
|
|
66
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="qss-w-4 qss-h-4"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
|
67
|
+
</button>
|
|
68
|
+
<div id="pp-portal-link-menu-dropdown" class="qss-link-menu-dropdown qss-absolute qss-w-20 qss-bg-[#1a1d23] qss-border qss-border-slate-800 qss-rounded qss-shadow-2xl qss-z-[100] qss-hidden group-hover/link-menu:qss-block qss-pointer-events-auto" style="--dropdown-top: auto; --dropdown-left: auto;">
|
|
69
|
+
<div class="qss-mirror-list qss-flex qss-flex-col qss-py-1">
|
|
70
|
+
<!-- Populated in JS -->
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<button class="qss-pane-action-btn qss-close-split-btn qss-flex qss-items-center qss-justify-center qss-w-6 qss-h-full qss-text-slate-500 hover:qss-text-red-400 hover:qss-bg-white/5 qss-transition-all qss-hidden" title="Close Split" data-action="close-split">
|
|
76
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="qss-w-3.5 qss-h-3.5"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
|
|
77
|
+
</button>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<div class="qss-flex-1 qss-flex qss-overflow-hidden">
|
|
82
|
+
<!-- Contextual Snippet Drawer -->
|
|
83
|
+
<div class="qss-snippet-drawer qss-border-r qss-border-slate-800 qss-bg-[#111418] qss-overflow-hidden qss-transition-all qss-duration-300 qss-flex qss-flex-col" style="--drawer-w: 0px;">
|
|
84
|
+
<div class="qss-flex qss-items-center qss-justify-between qss-px-2 qss-py-2 qss-border-b qss-border-slate-800 qss-bg-[#16191e]">
|
|
85
|
+
<span class="qss-text-size[11] qss-font-bold qss-text-slate-400 qss-uppercase qss-tracking-widest">Code Help</span>
|
|
86
|
+
<button class="qss-pane-action-btn qss-close-drawer-btn qss-text-slate-600 hover:qss-text-white qss-transition-colors" data-action="toggle-snippets">
|
|
87
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="qss-w-4 qss-h-4"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
|
|
88
|
+
</button>
|
|
89
|
+
</div>
|
|
90
|
+
<div class="qss-drawer-content qss-flex-1 qss-overflow-y-auto qss-custom-scrollbar qss-p-2 qss-space-y-2"></div>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<div class="qss-monaco-editor-target qss-flex-1 qss-bg-[#1e1e1e] qss-overflow-hidden"></div>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<!-- Fix Suggestions Footer -->
|
|
97
|
+
<div class="qss-fix-footer qss-border-t qss-border-red-900/40 qss-bg-red-900/10 qss-hidden qss-overflow-hidden qss-transition-all qss-duration-300" style="--footer-h: 0px;">
|
|
98
|
+
<div class="qss-flex qss-flex-col qss-p-2 qss-gap-2">
|
|
99
|
+
<div class="qss-flex qss-items-center qss-justify-between">
|
|
100
|
+
<div class="qss-flex qss-items-center qss-gap-2">
|
|
101
|
+
<div class="qss-w-2 qss-h-2 qss-rounded-full qss-bg-red-500 qss-animate-pulse"></div>
|
|
102
|
+
<span class="qss-text-[10px] qss-font-bold qss-text-red-400 qss-uppercase qss-tracking-widest">Diagnostic</span>
|
|
103
|
+
</div>
|
|
104
|
+
<button class="qss-close-fix-btn qss-text-slate-500 hover:qss-text-white qss-transition-colors">
|
|
105
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="qss-w-3 qss-h-3"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
|
|
106
|
+
</button>
|
|
107
|
+
</div>
|
|
108
|
+
<div class="qss-fix-message qss-text-[10px] qss-text-slate-300 qss-font-mono qss-leading-tight"></div>
|
|
109
|
+
<div class="qss-flex qss-gap-2 qss-mt-1">
|
|
110
|
+
<button class="qss-apply-fix-btn qss-bg-indigo-600 hover:qss-bg-indigo-500 qss-text-white qss-text-[9px] qss-font-bold qss-px-2 qss-py-1 qss-rounded qss-transition-colors qss-uppercase">Apply AI Fix</button>
|
|
111
|
+
<button class="qss-explain-fix-btn qss-bg-slate-800 hover:qss-bg-slate-700 qss-text-slate-300 qss-text-[9px] qss-font-bold qss-px-2 qss-py-1 qss-rounded qss-transition-colors qss-uppercase">Explain</button>
|
|
112
|
+
</div>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
</template>
|
|
117
|
+
|
|
118
|
+
<template id="qss-tpl-editor-tab">
|
|
119
|
+
<div class="qss-editor-tab qss-flex qss-items-center qss-gap-1.5 qss-px-2 qss-h-full qss-text-[10px] qss-font-mono qss-text-slate-300 qss-cursor-pointer qss-whitespace-nowrap qss-select-none qss-border-r qss-border-slate-800/50 qss-transition-colors qss-flex-shrink-0" data-qss-active="false">
|
|
120
|
+
<span class="qss-tab-icon qss-w-3.5 qss-h-3.5 qss-flex qss-items-center qss-justify-center"></span>
|
|
121
|
+
<span class="qss-editor-tab-label qss-select-none"></span>
|
|
122
|
+
<div class="qss-dirty-indicator qss-w-1.5 qss-h-1.5 qss-rounded-full qss-bg-orange-500 qss-ml-1 qss-hidden"></div>
|
|
123
|
+
<span class="qss-editor-tab-close qss-text-slate-600 hover:qss-text-red-400 qss-ml-1 qss-transition-colors qss-leading-none qss-text-size[11]">×</span>
|
|
124
|
+
</div>
|
|
125
|
+
</template>
|
|
126
|
+
|
|
127
|
+
<template id="qss-tpl-editor-buffer-item">
|
|
128
|
+
<button class="qss-buffer-item qss-flex qss-items-center qss-gap-2 qss-px-2 qss-py-1.5 hover:qss-bg-indigo-500/10 qss-text-[10px] qss-transition-colors qss-text-left qss-w-full" data-qss-active="false">
|
|
129
|
+
<span class="qss-item-icon qss-w-3 qss-h-3 qss-flex qss-items-center qss-justify-center"></span>
|
|
130
|
+
<span class="qss-truncate qss-flex-1"></span>
|
|
131
|
+
<div class="qss-dirty-indicator qss-w-1.5 qss-h-1.5 qss-rounded-full qss-bg-orange-500 qss-hidden"></div>
|
|
132
|
+
</button>
|
|
133
|
+
</template>
|
|
134
|
+
|
|
135
|
+
<template id="qss-tpl-header-actions">
|
|
136
|
+
<div class="qss-flex qss-items-center qss-gap-1">
|
|
137
|
+
<button class="qss-pane-action-btn qss-header-action-btn qss-flex qss-items-center qss-justify-center qss-w-7 qss-h-7 qss-text-slate-500 hover:qss-text-white hover:qss-bg-white/5 qss-transition-all" title="Run Tool" data-action="run">
|
|
138
|
+
<div class="qss-flex qss-items-center">
|
|
139
|
+
<!-- Injected via updateRunUI -->
|
|
140
|
+
</div>
|
|
141
|
+
</button>
|
|
142
|
+
<button class="qss-pane-action-btn qss-header-action-btn qss-flex qss-items-center qss-justify-center qss-w-7 qss-h-7 qss-text-slate-500 hover:qss-text-orange-400 hover:qss-bg-white/5 qss-transition-all" title="Toggle Code Help" data-action="toggle-snippets">
|
|
143
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="qss-w-3.5 qss-h-3.5"><path d="M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .5 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5"></path><path d="M9 18h6"></path><path d="M10 22h4"></path></svg>
|
|
144
|
+
</button>
|
|
145
|
+
<button class="qss-pane-action-btn qss-header-action-btn qss-flex qss-items-center qss-justify-center qss-w-7 qss-h-7 qss-text-slate-500 hover:qss-text-emerald-400 hover:qss-bg-white/5 qss-transition-all" title="Save File (Ctrl+S)" data-action="save">
|
|
146
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="qss-w-3.5 qss-h-3.5"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path><polyline points="17 21 17 13 7 13 7 21"></polyline><polyline points="7 3 7 8 15 8"></polyline></svg>
|
|
147
|
+
</button>
|
|
148
|
+
<button class="qss-pane-action-btn qss-header-action-btn qss-flex qss-items-center qss-justify-center qss-w-7 qss-h-7 qss-text-slate-500 hover:qss-text-indigo-400 hover:qss-bg-white/5 qss-transition-all" title="Add Split" data-action="split">
|
|
149
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="qss-w-3.5 qss-h-3.5"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"></rect><line x1="9" y1="3" x2="9" y2="21"></line></svg>
|
|
150
|
+
</button>
|
|
151
|
+
<button class="qss-pane-action-btn qss-header-action-btn qss-flex qss-items-center qss-justify-center qss-w-7 qss-h-7 qss-text-slate-500 hover:qss-text-indigo-400 hover:qss-bg-white/5 qss-transition-all" title="Link/Unlink Mirror" data-action="toggle-link">
|
|
152
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="qss-w-4 qss-h-4"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
|
153
|
+
</button>
|
|
154
|
+
</div>
|
|
155
|
+
</template>
|
|
156
|
+
|
|
157
|
+
<template id="qss-tpl-snippet-group">
|
|
158
|
+
<div class="qss-snippet-group qss-mb-2 qss-border qss-border-slate-800 qss-rounded qss-bg-white/[0.01]" data-category="">
|
|
159
|
+
<div class="qss-category-header qss-flex qss-items-center qss-justify-between qss-px-2 qss-py-1.5 qss-cursor-pointer hover:qss-bg-white/[0.03] qss-transition-colors group">
|
|
160
|
+
<span class="qss-category-label qss-text-[9px] qss-font-bold qss-text-slate-500 qss-uppercase qss-tracking-widest group-hover:qss-text-slate-300"></span>
|
|
161
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="qss-w-3 qss-h-3 qss-text-slate-600 qss-transform qss-transition-transform qss-duration-200"><polyline points="6 9 12 15 18 9"></polyline></svg>
|
|
162
|
+
</div>
|
|
163
|
+
<div class="qss-category-body qss-hidden qss-flex qss-flex-col qss-gap-2 qss-p-2 qss-border-t qss-border-slate-800/50">
|
|
164
|
+
<!-- Tiles injected here -->
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
</template>
|
|
168
|
+
|
|
169
|
+
<template id="qss-tpl-snippet-tile">
|
|
170
|
+
<div class="qss-snippet-tile qss-border qss-border-slate-800/50 qss-bg-black/20 qss-rounded qss-overflow-hidden">
|
|
171
|
+
<div class="qss-p-2 qss-space-y-1.5">
|
|
172
|
+
<div class="qss-flex qss-items-center qss-justify-between">
|
|
173
|
+
<span class="qss-snippet-name qss-text-[10px] qss-font-bold qss-text-slate-300 qss-truncate"></span>
|
|
174
|
+
<button class="qss-insert-btn qss-flex qss-items-center qss-gap-0.5 qss-text-[7px] qss-font-bold qss-text-indigo-400/70 hover:qss-text-indigo-300 qss-transition-colors qss-bg-transparent qss-border-none qss-p-0">
|
|
175
|
+
INSERT
|
|
176
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" class="qss-w-2 qss-h-2"><polyline points="9 18 15 12 9 6"></polyline></svg>
|
|
177
|
+
</button>
|
|
178
|
+
</div>
|
|
179
|
+
<div class="qss-snippet-desc qss-text-[9px] qss-text-slate-400 qss-italic qss-leading-tight"></div>
|
|
180
|
+
<div class="qss-snippet-code-preview qss-bg-black/60 qss-rounded qss-p-1.5 qss-font-mono qss-text-[9px] qss-text-slate-400 qss-border qss-border-white/5 qss-overflow-x-auto qss-custom-scrollbar"></div>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
</template>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<!-- Perspective Explorer Shell (Drawn) -->
|
|
2
|
+
<div id="qss-file-explorer-shell" class="qss-absolute pos-x[0] pos-y[0] w-pct[1000] h-pct[1000] qss-bg-[#16191e] qss-overflow-hidden qss-font-sans">
|
|
3
|
+
|
|
4
|
+
<!-- Smart Search Area (Drawn) -->
|
|
5
|
+
<div id="qss-sidebar-search" class="qss-absolute pos-x[0] pos-y[0] w-pct[1000] h[45] qss-p-2 qss-border-b qss-border-slate-800/50 qss-bg-[#1a1d23]/30">
|
|
6
|
+
<div class="qss-bg-[#0f1115] qss-rounded qss-border qss-border-slate-800 qss-px-2 qss-py-1.5 qss-flex qss-items-center qss-gap-2 qss-group focus-within:qss-border-indigo-500/50 qss-transition-colors">
|
|
7
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="qss-w-3.5 qss-h-3.5 qss-text-slate-600 group-focus-within:qss-text-indigo-400"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
|
|
8
|
+
<input type="text" placeholder="Filter files, features, or specs..." class="qss-bg-transparent qss-border-none qss-text-[10px] qss-outline-none qss-w-full placeholder:qss-text-slate-600 qss-text-slate-300">
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<!-- Tree Area Wrapper (Calculated offset) -->
|
|
13
|
+
<div id="qss-explorer-content" class="qss-absolute pos-x[0] pos-y[45] w-pct[1000] qss-fill-h qss-overflow-y-auto qss-custom-scrollbar">
|
|
14
|
+
<%= render "parapet/activities/explorer_base" %>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<!-- Progress / Status Area (Fixed at bottom) -->
|
|
18
|
+
<div id="qss-progress-area" class="qss-absolute pos-x[0] pos-b[0] w-pct[1000] h[4] depth[ui]">
|
|
19
|
+
<%= render "parapet/activities/progress_area" %>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<%= render "parapet/activities/file_explorer/viewport_scripts" %>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<turbo-frame id="active-widget">
|
|
2
|
+
<div class="qss-p-3 qss-flex qss-flex-col qss-h-full qss-overflow-hidden">
|
|
3
|
+
<div class="qss-flex qss-items-center qss-gap-2 qss-mb-2">
|
|
4
|
+
<i class="lucide-hammer qss-w-3.5 qss-h-3.5 qss-text-amber-400"></i>
|
|
5
|
+
<span class="qss-text-[10px] qss-font-bold qss-uppercase qss-tracking-widest qss-text-slate-400">Fix Suggestions</span>
|
|
6
|
+
</div>
|
|
7
|
+
<div class="qss-flex-1 qss-overflow-y-auto custom-scrollbar">
|
|
8
|
+
<div class="qss-text-[10px] qss-text-slate-500 qss-italic qss-px-1">
|
|
9
|
+
No active failures detected. Focus on a failing spec node to see suggestions.
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
</turbo-frame>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<% action_phrase = {
|
|
2
|
+
"file_saved" => "saved #{activity.details.fetch("file_path", "a file")}",
|
|
3
|
+
"test_run" => "ran tests",
|
|
4
|
+
"publish" => "published changes"
|
|
5
|
+
}.fetch(activity.action) { activity.action.humanize.downcase } %>
|
|
6
|
+
<%= "#{actor_name} #{action_phrase}" %>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<div class="qss-bg-white qss-h-full qss-w-full qss-rounded qss-overflow-hidden qss-flex qss-flex-col">
|
|
2
|
+
<div class="qss-h-6 qss-bg-slate-100 qss-border-b qss-flex qss-items-center qss-px-2 qss-gap-2">
|
|
3
|
+
<div class="qss-flex qss-gap-1">
|
|
4
|
+
<div class="qss-w-2 qss-h-2 qss-rounded-full qss-bg-red-400"></div>
|
|
5
|
+
<div class="qss-w-2 qss-h-2 qss-rounded-full qss-bg-amber-400"></div>
|
|
6
|
+
<div class="qss-w-2 qss-h-2 qss-rounded-full qss-bg-emerald-400"></div>
|
|
7
|
+
</div>
|
|
8
|
+
<div class="qss-flex-grow qss-bg-white qss-border qss-rounded qss-h-4 qss-flex qss-items-center qss-px-2 qss-text-[8px] qss-text-slate-400">localhost:3000/parapet</div>
|
|
9
|
+
</div>
|
|
10
|
+
<div class="qss-flex-grow qss-flex qss-items-center qss-justify-center qss-bg-slate-50">
|
|
11
|
+
<div class="qss-text-slate-300 qss-font-bold qss-text-xl qss-tracking-tighter">PARAPET</div>
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<!-- Perspective Filters -->
|
|
2
|
+
<div id="qss-perspective-filters" class="qss anchored px[8] py[6] border-b[1] border-slate-800 horizontal v-mid spaced gap[6] bg-brand-header">
|
|
3
|
+
|
|
4
|
+
<!-- Test Suite Perspectives -->
|
|
5
|
+
<div class="suite-group horizontal w-full gap[6]" data-suites="tests">
|
|
6
|
+
<% ['project', 'registry', 'coverage'].each do |view| %>
|
|
7
|
+
<%
|
|
8
|
+
current_view = local_assigns[:explorer_type] || @explorer_type || 'project'
|
|
9
|
+
is_active = (view == current_view)
|
|
10
|
+
active_classes = "active bg-indigo-500/10 border-indigo-500/30 text-indigo-400"
|
|
11
|
+
inactive_classes = "bg-slate-800 border-slate-700 text-slate-500"
|
|
12
|
+
%>
|
|
13
|
+
<%= link_to view.capitalize, parapet.explorer_path(type: view),
|
|
14
|
+
class: "perspective-btn flex-1 px[4] py[2] rounded[2] text-size[5] weight[700] uppercase tracking[tight] border[1] smooth text-center #{is_active ? active_classes : inactive_classes}",
|
|
15
|
+
data: { turbo_stream: true, view: view } %>
|
|
16
|
+
<% end %>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<!-- CSS Suite Perspectives -->
|
|
20
|
+
<div class="suite-group horizontal w-full gap[6]" data-suites="css">
|
|
21
|
+
<% ['grammar', 'css', 'views'].each do |view| %>
|
|
22
|
+
<%
|
|
23
|
+
current_view = local_assigns[:explorer_type] || @explorer_type || 'grammar'
|
|
24
|
+
is_active = (view == current_view)
|
|
25
|
+
active_classes = "active bg-indigo-500/10 border-indigo-500/30 text-indigo-400"
|
|
26
|
+
inactive_classes = "bg-slate-800 border-slate-700 text-slate-500"
|
|
27
|
+
%>
|
|
28
|
+
<%= link_to view.capitalize, parapet.explorer_path(type: view),
|
|
29
|
+
class: "perspective-btn flex-1 px[4] py[2] rounded[2] text-size[5] weight[700] uppercase tracking[tight] border[1] smooth text-center #{is_active ? active_classes : inactive_classes}",
|
|
30
|
+
data: { turbo_stream: true, view: view } %>
|
|
31
|
+
<% end %>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<%= render 'parapet/activities/file_explorer/perspective_scripts' %>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<!-- Diagnostic Area: Consolidated Health & Context -->
|
|
2
|
+
<%
|
|
3
|
+
summary = local_assigns[:summary] || explorer_summary('project')
|
|
4
|
+
counts = summary['counts'] || {}
|
|
5
|
+
total = summary['total_files'].to_i
|
|
6
|
+
|
|
7
|
+
pass_count = counts['green'].to_i
|
|
8
|
+
fail_count = counts['red'].to_i
|
|
9
|
+
warn_count = counts['orange'].to_i
|
|
10
|
+
grey_count = counts['grey'].to_i
|
|
11
|
+
|
|
12
|
+
pass_pct = total > 0 ? (pass_count.to_f / total * 100).round : 0
|
|
13
|
+
fail_pct = total > 0 ? (fail_count.to_f / total * 100).round : 0
|
|
14
|
+
warn_pct = total > 0 ? (warn_count.to_f / total * 100).round : 0
|
|
15
|
+
grey_pct = total > 0 ? (grey_count.to_f / total * 100).round : 0
|
|
16
|
+
|
|
17
|
+
all_segments = [
|
|
18
|
+
{ count: pass_count, pct: pass_pct, bar_class: "qss-bg-emerald-500 qss-shadow-[0_0_8px_rgba(16,185,129,0.3)]", text_class: "qss-text-emerald-400/70" },
|
|
19
|
+
{ count: fail_count, pct: fail_pct, bar_class: "qss-bg-red-500 qss-shadow-[0_0_8px_rgba(239,68,68,0.3)]", text_class: "qss-text-red-400/70" },
|
|
20
|
+
{ count: warn_count, pct: warn_pct, bar_class: "qss-bg-orange-500", text_class: "qss-text-orange-400/70" },
|
|
21
|
+
{ count: grey_count, pct: grey_pct, bar_class: "qss-bg-slate-500", text_class: "qss-text-slate-400/70" },
|
|
22
|
+
]
|
|
23
|
+
segments = all_segments.select { |s| s[:count] > 0 }
|
|
24
|
+
%>
|
|
25
|
+
<div id="qss-progress-area" class="qss anchored w-full h[28] vertical v-mid px[8] py[4] bg-white/2 border-b[1] border-slate-800/50">
|
|
26
|
+
<!-- Health Analytics Cluster -->
|
|
27
|
+
<div class="qss anchored horizontal v-mid w-full h[4] gap[1]">
|
|
28
|
+
<% if segments.any? %>
|
|
29
|
+
<% segments.each_with_index do |seg, idx| %>
|
|
30
|
+
<% flex_val = [seg[:pct], 1].max %>
|
|
31
|
+
<div class="qss anchored h-full <%= seg[:bar_class] %> rounded[2]" style="flex: <%= flex_val %> 1 0%;"></div>
|
|
32
|
+
<% end %>
|
|
33
|
+
<% else %>
|
|
34
|
+
<div class="qss anchored h-full w-full bg-slate-800/40 rounded[2] border[1] border-white/5"></div>
|
|
35
|
+
<% end %>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= render partial: 'parapet/activities/explorer_base', locals: { type: 'project', tree_data: @tree_data } %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= render partial: 'parapet/activities/explorer_base', locals: { type: 'registry', tree_data: @tree_data } %>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<div class="qss-space-y-3">
|
|
2
|
+
<div class="qss-flex qss-items-center qss-bg-slate-900 qss-border qss-border-slate-800 qss-rounded qss-px-2 qss-py-1.5 qss-gap-2">
|
|
3
|
+
<i class="lucide-search qss-w-3 qss-h-3 qss-text-slate-500"></i>
|
|
4
|
+
<input type="text" placeholder="Search files, symbols..." class="qss-bg-transparent qss-border-none qss-outline-none qss-text-[10px] qss-w-full qss-text-slate-300">
|
|
5
|
+
</div>
|
|
6
|
+
<div class="qss-space-y-1">
|
|
7
|
+
<div class="qss-text-[9px] qss-font-bold qss-text-slate-600 qss-uppercase qss-tracking-widest qss-px-1">Recent Searches</div>
|
|
8
|
+
<div class="qss-text-[10px] qss-text-slate-400 qss-px-2 qss-py-1 hover:qss-bg-slate-800 qss-rounded qss-cursor-pointer">activity-cards.js</div>
|
|
9
|
+
<div class="qss-text-[10px] qss-text-slate-400 qss-px-2 qss-py-1 hover:qss-bg-slate-800 qss-rounded qss-cursor-pointer">dashboard/index.html.erb</div>
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
(function() {
|
|
3
|
+
const STORAGE_KEY = 'parapet-explorer-view';
|
|
4
|
+
|
|
5
|
+
function updateUI(filters, view) {
|
|
6
|
+
filters.querySelectorAll('.qss-perspective-btn').forEach(btn => {
|
|
7
|
+
if (btn.dataset.view === view) {
|
|
8
|
+
btn.classList.add('qss-active', 'qss-bg-indigo-500/10', 'qss-border-indigo-500/30', 'qss-text-indigo-400');
|
|
9
|
+
btn.classList.remove('qss-bg-slate-800/50', 'qss-border-slate-700', 'qss-text-slate-500');
|
|
10
|
+
} else {
|
|
11
|
+
btn.classList.remove('qss-active', 'qss-bg-indigo-500/10', 'qss-border-indigo-500/30', 'qss-text-indigo-400');
|
|
12
|
+
btn.classList.add('qss-bg-slate-800/50', 'qss-border-slate-700', 'qss-text-slate-500');
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function initPerspectiveFilters() {
|
|
18
|
+
const filters = document.getElementById('qss-perspective-filters');
|
|
19
|
+
if (!filters || filters._perspectiveInit) return;
|
|
20
|
+
filters._perspectiveInit = true;
|
|
21
|
+
|
|
22
|
+
const savedView = localStorage.getItem(STORAGE_KEY);
|
|
23
|
+
const activeBtn = filters.querySelector('.qss-perspective-btn.qss-active');
|
|
24
|
+
const currentView = activeBtn ? activeBtn.dataset.view : 'project';
|
|
25
|
+
|
|
26
|
+
console.log("Parapet: Perspective init. Current:", currentView, "Saved:", savedView);
|
|
27
|
+
|
|
28
|
+
// 1. Restore on fresh load if needed
|
|
29
|
+
if (savedView && savedView !== currentView && !window._parapetRestoring) {
|
|
30
|
+
const targetBtn = filters.querySelector(`.qss-perspective-btn[data-view="${savedView}"]`);
|
|
31
|
+
if (targetBtn) {
|
|
32
|
+
console.log("Parapet: Restoring perspective view:", savedView);
|
|
33
|
+
window._parapetRestoring = true;
|
|
34
|
+
targetBtn.click();
|
|
35
|
+
setTimeout(() => window._parapetRestoring = false, 500);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 2. Click listener
|
|
41
|
+
filters.addEventListener('click', (e) => {
|
|
42
|
+
const btn = e.target.closest('.qss-perspective-btn');
|
|
43
|
+
if (btn) {
|
|
44
|
+
const view = btn.dataset.view;
|
|
45
|
+
console.log("Parapet: Perspective clicked:", view);
|
|
46
|
+
localStorage.setItem(STORAGE_KEY, view);
|
|
47
|
+
// Update UI immediately for snappiness
|
|
48
|
+
updateUI(filters, view);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
document.addEventListener('turbo:load', initPerspectiveFilters);
|
|
54
|
+
if (document.readyState === 'complete' || document.readyState === 'interactive') {
|
|
55
|
+
initPerspectiveFilters();
|
|
56
|
+
}
|
|
57
|
+
})();
|
|
58
|
+
</script>
|
|
File without changes
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
(function() {
|
|
3
|
+
const viewport = document.getElementById('qss-explorer-viewport');
|
|
4
|
+
const expandBtn = document.getElementById('qss-explorer-expand-all');
|
|
5
|
+
const collapseBtn = document.getElementById('qss-explorer-collapse-all');
|
|
6
|
+
|
|
7
|
+
if (!viewport || !expandBtn || !collapseBtn) return;
|
|
8
|
+
|
|
9
|
+
function setAllNodesState(expand) {
|
|
10
|
+
const containers = viewport.querySelectorAll('.qss-children-container');
|
|
11
|
+
const nodes = viewport.querySelectorAll('.qss-explorer-node');
|
|
12
|
+
|
|
13
|
+
nodes.forEach(node => {
|
|
14
|
+
if (expand) {
|
|
15
|
+
node.classList.add('qss-is-open');
|
|
16
|
+
} else {
|
|
17
|
+
node.classList.remove('qss-is-open');
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
containers.forEach(container => {
|
|
22
|
+
if (expand) {
|
|
23
|
+
container.style.display = 'block';
|
|
24
|
+
} else {
|
|
25
|
+
container.style.display = 'none';
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
expandBtn.addEventListener('click', () => setAllNodesState(true));
|
|
31
|
+
collapseBtn.addEventListener('click', () => setAllNodesState(false));
|
|
32
|
+
})();
|
|
33
|
+
</script>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<div id="pp-styles-workbench" class="qss w-full h-full scroll[hidden]">
|
|
2
|
+
<!-- Command Bar -->
|
|
3
|
+
<div id="pp-workbench-command-bar" class="qss absolute pos-x[0] pos-y[0] w-full h[20] bg-brand-header border-b[1] border-slate-800 horizontal v-mid px[12] spaced depth[ui]">
|
|
4
|
+
<!-- Interaction States -->
|
|
5
|
+
<div class="qss horizontal gap[6] v-mid">
|
|
6
|
+
<span class="qss text-size[5] text-slate-500 weight[700] uppercase tracking[tighter] mr[4]">States</span>
|
|
7
|
+
<button class="qss px[6] py[2] bg-slate-800 rounded[2] text-size[6] text-slate-400 hover:text-white smooth border-none clickable" data-state="hover">HOVER</button>
|
|
8
|
+
<button class="qss px[6] py[2] bg-slate-800 rounded[2] text-size[6] text-slate-400 hover:text-white smooth border-none clickable" data-state="active">ACTIVE</button>
|
|
9
|
+
<button class="qss px[6] py[2] bg-slate-800 rounded[2] text-size[6] text-slate-400 hover:text-white smooth border-none clickable" data-state="focus">FOCUS</button>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<!-- Spatial Toggles -->
|
|
13
|
+
<div class="qss horizontal gap[10] v-mid">
|
|
14
|
+
<div class="qss horizontal gap[4] v-mid border-r[1] border-slate-800 pr[10]">
|
|
15
|
+
<span class="qss text-size[5] text-slate-500 weight[700] uppercase tracking[tighter]">Grid</span>
|
|
16
|
+
<button class="qss w[24] h[14] bg-slate-800 rounded[2] text-size[6] text-slate-400 centered border-none clickable" data-grid="10">10</button>
|
|
17
|
+
<button class="qss w[24] h[14] bg-slate-800 rounded[2] text-size[6] text-slate-400 centered border-none clickable" data-grid="50">50</button>
|
|
18
|
+
<button class="qss w[24] h[14] bg-slate-800 rounded[2] text-size[6] text-slate-400 centered border-none clickable" data-grid="100">100</button>
|
|
19
|
+
</div>
|
|
20
|
+
<button id="pp-toggle-anchors" class="qss horizontal gap[4] v-mid px[6] py[2] bg-slate-800 rounded[2] text-size[6] text-slate-400 hover:text-indigo-400 smooth border-none clickable">
|
|
21
|
+
<i class="icon-anchor text-size[7]"></i>
|
|
22
|
+
<span>ANCHORS</span>
|
|
23
|
+
</button>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<!-- Center Workspace -->
|
|
28
|
+
<div id="pp-workspace-wrapper" class="qss anchored pos-x[0] pos-y[20] w-full pos-b[0]">
|
|
29
|
+
<!-- Agentic Canvas Label -->
|
|
30
|
+
<div class="qss absolute pos-x[16] pos-y[8] depth[ui] ghost">
|
|
31
|
+
<span class="qss text-size[9] weight[900] text-slate-500 uppercase tracking[widest]">Agentic Canvas</span>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<!-- Live Preview Canvas -->
|
|
35
|
+
<div id="pp-mockup-container" class="qss absolute pos-x[0] pos-y[0] w-full pos-b[200] scroll[auto] border-b[1] border-slate-800">
|
|
36
|
+
<!-- Content rendered by JS into Shadow DOM -->
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<!-- Monaco Editor (Bottom Console) -->
|
|
40
|
+
<div id="pp-workspace-console" class="qss absolute pos-x[0] pos-b[0] w-full h[200] bg-brand-header">
|
|
41
|
+
<div id="pp-console-resizer" class="qss absolute pos-x[0] pos-y[0] w-full h[4] cursor-row-resize bg-transparent hover:bg-indigo-500/50 smooth"></div>
|
|
42
|
+
<div class="qss absolute w-full h[24] bg-slate-900 border-b[1] border-slate-800 px[12] horizontal v-mid spaced">
|
|
43
|
+
<span id="pp-source-filename" class="qss text-size[8] text-slate-500 font[mono]">no-file-selected.qss</span>
|
|
44
|
+
</div>
|
|
45
|
+
<div class="qss absolute w-full pos-y[24] pos-b[0] horizontal">
|
|
46
|
+
<div id="pp-monaco-source" class="qss anchored h-full flex-1 border-r[1] border-slate-800 foreign"></div>
|
|
47
|
+
<div id="pp-monaco-compiled" class="qss anchored h-full flex-1 foreign"></div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<!-- Workspace Layers -->
|
|
2
|
+
<div id="pp-workspace-layers" class="qss anchored depth[canvas] w-full h-full contain-layout">
|
|
3
|
+
<div class="qss workspace-layer anchored layer-novice" data-layer="0"></div>
|
|
4
|
+
<div class="qss workspace-layer anchored layer-intermediate" data-layer="1"></div>
|
|
5
|
+
<div class="qss workspace-layer anchored layer-advanced" data-layer="2"></div>
|
|
6
|
+
<div class="qss workspace-layer anchored layer-power" data-layer="3"></div>
|
|
7
|
+
<div class="qss workspace-layer anchored layer-floating" id="pp-floating-layer"></div>
|
|
8
|
+
|
|
9
|
+
<div class="qss anchored horizontal v-mid h-mid w-full h-full">
|
|
10
|
+
<div class="qss suite-group anchored text-slate-700 italic opacity[500] <%= @active_suite.present? ? 'hidden' : '' %>" data-suites="none">
|
|
11
|
+
Workspace Stable - Select a Suite
|
|
12
|
+
</div>
|
|
13
|
+
<div class="qss suite-group anchored w-full h-full <%= @active_suite == 'css' ? '' : 'hidden' %>" data-suites="css">
|
|
14
|
+
<%= render "parapet/css_suite/workbench" %>
|
|
15
|
+
</div>
|
|
16
|
+
<% suite_placeholders = {
|
|
17
|
+
'tests' => 'Test Suite: In Development',
|
|
18
|
+
'intentions' => 'Intentions Suite: In Development',
|
|
19
|
+
'signal' => 'Signal Suite: Coming Soon',
|
|
20
|
+
'monitor' => 'Process Monitor: Coming Soon',
|
|
21
|
+
'polyglot' => 'Polyglot Suite: Coming Soon',
|
|
22
|
+
'build' => 'Build Suite: Coming Soon'
|
|
23
|
+
} %>
|
|
24
|
+
<div class="qss suite-group anchored w-full h-full <%= suite_placeholders.key?(@active_suite) ? '' : 'hidden' %>" data-suites="placeholder">
|
|
25
|
+
<div class="qss absolute pos-x[center] pos-y[center] text-slate-500"><%= suite_placeholders[@active_suite] %></div>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<!-- Live Preview Popup -->
|
|
30
|
+
<div id="pp-preview-popup" class="qss absolute pos-r[16] pos-b[52] w[640] h[420] bg-brand-main border[1] border-slate-700 rounded[6] shadow[xl] depth[modal] hidden">
|
|
31
|
+
|
|
32
|
+
<!-- Popup Chrome -->
|
|
33
|
+
<div class="qss anchored w-full h[32] bg-brand-header border-b[1] border-slate-800 horizontal v-mid px[10] gap[8]">
|
|
34
|
+
<span class="qss anchored text-size[6] text-slate-500 font[mono] flex-1 truncate">
|
|
35
|
+
localhost:3000
|
|
36
|
+
</span>
|
|
37
|
+
<span id="pp-preview-pinned-badge" class="qss anchored text-size[5] weight[700] tracking[wider] text-blue-400 bg-blue-900/30 rounded[3] px[5] py[1] hidden">
|
|
38
|
+
PINNED
|
|
39
|
+
</span>
|
|
40
|
+
<button onclick="window.ParapetPreview.refresh()" title="Refresh" class="qss anchored bg-transparent border-none clickable text-slate-500 hover:text-slate-300 smooth centered w[20] h[20]">
|
|
41
|
+
<i class="icon-refresh-cw text-size[7]"></i>
|
|
42
|
+
</button>
|
|
43
|
+
<button onclick="window.ParapetPreview.togglePin()" title="Pin to front" id="pp-preview-pin-btn" class="qss anchored bg-transparent border-none clickable text-slate-500 hover:text-blue-400 smooth centered w[20] h[20]">
|
|
44
|
+
<i class="icon-pin text-size[7]"></i>
|
|
45
|
+
</button>
|
|
46
|
+
<button onclick="window.ParapetPreview.close()" title="Close" class="qss anchored bg-transparent border-none clickable text-slate-500 hover:text-red-500 smooth centered w[20] h[20] text-size[12]">×</button>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<!-- Iframe content -->
|
|
50
|
+
<iframe id="pp-preview-iframe"
|
|
51
|
+
src="about:blank"
|
|
52
|
+
class="qss anchored flex-1 w-full border-none bg-white foreign contain-layout"
|
|
53
|
+
|
|
54
|
+
sandbox="allow-same-origin allow-scripts allow-forms">
|
|
55
|
+
</iframe>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<!-- Activity Card Templates -->
|
|
59
|
+
<%= render "parapet/activities/file_editor" %>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<script>
|
|
63
|
+
window.ParapetPreview = (function() {
|
|
64
|
+
var popup = document.getElementById('pp-preview-popup');
|
|
65
|
+
var badge = document.getElementById('pp-preview-pinned-badge');
|
|
66
|
+
var pinBtn = document.getElementById('pp-preview-pin-btn');
|
|
67
|
+
var iframe = document.getElementById('pp-preview-iframe');
|
|
68
|
+
var open = false;
|
|
69
|
+
var pinned = false;
|
|
70
|
+
|
|
71
|
+
function show() {
|
|
72
|
+
popup.classList.remove('hidden');
|
|
73
|
+
if (iframe.src === 'about:blank') iframe.src = 'http://localhost:3000';
|
|
74
|
+
open = true;
|
|
75
|
+
document.dispatchEvent(new CustomEvent('previewOpened'));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function hide() {
|
|
79
|
+
if (pinned) return;
|
|
80
|
+
popup.classList.add('hidden');
|
|
81
|
+
open = false;
|
|
82
|
+
document.dispatchEvent(new CustomEvent('previewClosed'));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
pinned: pinned,
|
|
87
|
+
toggle: function() { open ? hide() : show(); },
|
|
88
|
+
close: function() {
|
|
89
|
+
pinned = false;
|
|
90
|
+
this.pinned = false;
|
|
91
|
+
popup.classList.remove('border-blue-500');
|
|
92
|
+
badge.classList.add('hidden');
|
|
93
|
+
pinBtn.classList.remove('text-blue-400');
|
|
94
|
+
hide();
|
|
95
|
+
},
|
|
96
|
+
refresh: function() { if (iframe.src !== 'about:blank') { iframe.src = iframe.src; } },
|
|
97
|
+
togglePin: function() {
|
|
98
|
+
pinned = !pinned;
|
|
99
|
+
this.pinned = pinned;
|
|
100
|
+
if (pinned) {
|
|
101
|
+
popup.classList.add('border-blue-500');
|
|
102
|
+
badge.classList.remove('hidden');
|
|
103
|
+
pinBtn.classList.add('text-blue-400');
|
|
104
|
+
if (!open) show();
|
|
105
|
+
} else {
|
|
106
|
+
popup.classList.remove('border-blue-500');
|
|
107
|
+
badge.classList.add('hidden');
|
|
108
|
+
pinBtn.classList.remove('text-blue-400');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
})();
|
|
113
|
+
</script>
|