CoolFace
Datasetpublic

basant307/AI_Governance_Project

sourceHugging Faceapache-2.0updated 2mo agoView on Hugging Face
0likes48downloads
Qualitative.tsx790 linesDownload Raw Back to src
1/* eslint-disable @typescript-eslint/no-explicit-any */2import { useState } from 'react';3import { DashboardCards, HeatmapSection } from './Charts';4import type { InsightData, QualitativeData } from './types';5import { CopyButton, MarkdownText } from './Components';6// eslint-disable-next-line @typescript-eslint/no-unused-vars7import React from 'react';8 9// -----------------------------------------------------------------------------10// Qualitative Insight Components11// -----------------------------------------------------------------------------12 13function hasMeaningfulText(value: unknown): value is string {14  return typeof value === 'string' && value.trim().length > 0;15}16 17export interface AtAGlanceTargetSections {18  wins: boolean;19  friction: boolean;20  features: boolean;21  horizon: boolean;22}23 24export function AtAGlance({25  qualitative,26  targetSections,27}: {28  qualitative: QualitativeData;29  targetSections: AtAGlanceTargetSections;30}) {31  const { atAGlance } = qualitative;32  if (!atAGlance) return null;33 34  const sections = [35    {36      key: 'wins',37      label: "What's working:",38      body: atAGlance.whats_working,39      href: '#section-wins',40      link: 'Impressive Things You Did →',41      showLink: targetSections.wins,42    },43    {44      key: 'friction',45      label: "What's hindering you:",46      body: atAGlance.whats_hindering,47      href: '#section-friction',48      link: 'Where Things Go Wrong →',49      showLink: targetSections.friction,50    },51    {52      key: 'features',53      label: 'Quick wins to try:',54      body: atAGlance.quick_wins,55      href: '#section-features',56      link: 'Features to Try →',57      showLink: targetSections.features,58    },59    {60      key: 'horizon',61      label: 'Ambitious workflows:',62      body: atAGlance.ambitious_workflows,63      href: '#section-horizon',64      link: 'On the Horizon →',65      showLink: targetSections.horizon,66    },67  ].filter((section) => hasMeaningfulText(section.body));68 69  if (sections.length === 0) return null;70 71  return (72    <div className="at-a-glance">73      <div className="glance-title">At a Glance</div>74      <div className="glance-sections">75        {sections.map((section) => (76          <div key={section.key} className="glance-section">77            <strong>{section.label}</strong>{' '}78            <MarkdownText>{section.body}</MarkdownText>79            {section.showLink && (80              <a href={section.href} className="see-more">81                {section.link}82              </a>83            )}84          </div>85        ))}86      </div>87    </div>88  );89}90 91export interface NavTocSection {92  href: string;93  label: string;94}95 96export function NavToc({ sections }: { sections: NavTocSection[] }) {97  if (sections.length === 0) return null;98 99  return (100    <nav className="nav-toc">101      {sections.map((section) => (102        <a key={section.href} href={section.href}>103          {section.label}104        </a>105      ))}106    </nav>107  );108}109 110export function ProjectAreas({111  qualitative,112  topGoals,113  topTools,114}: {115  qualitative: QualitativeData;116  topGoals?: Record<string, number>;117  topTools?: Record<string, number> | Array<[string, number]>;118}) {119  const { projectAreas } = qualitative;120 121  // Convert topTools (array of tuples) to object for chart if needed122  const topToolsObj = Array.isArray(topTools)123    ? Object.fromEntries(topTools)124    : topTools;125 126  return (127    <>128      <h2129        id="section-work"130        className="text-xl font-semibold text-slate-900 mt-8 mb-4"131      >132        What You Work On133      </h2>134 135      {Array.isArray(projectAreas?.areas) && projectAreas.areas.length > 0 && (136        <div className="project-areas mb-6">137          {projectAreas.areas.map((area, idx) => (138            <div key={idx} className="project-area">139              <div className="area-header">140                <span className="area-name">{area.name}</span>141                <span className="area-count">142                  ~{area.session_count} sessions143                </span>144              </div>145              <div className="area-desc">146                <MarkdownText>{area.description}</MarkdownText>147              </div>148            </div>149          ))}150        </div>151      )}152 153      <div154        style={{155          display: 'grid',156          gridTemplateColumns: 'repeat(2, 1fr)',157          gap: '24px',158          marginBottom: '24px',159        }}160      >161        {topGoals && Object.keys(topGoals).length > 0 && (162          <HorizontalBarChart163            data={topGoals}164            title="What You Wanted"165            color="#0ea5e9"166          />167        )}168        {topToolsObj && Object.keys(topToolsObj).length > 0 && (169          <HorizontalBarChart170            data={topToolsObj}171            title="Top Tools Used"172            color="#6366f1"173          />174        )}175      </div>176    </>177  );178}179 180export function InteractionStyle({181  qualitative,182  insights,183}: {184  qualitative: QualitativeData;185  insights: InsightData;186}) {187  const { interactionStyle } = qualitative;188  if (!interactionStyle) return null;189 190  return (191    <>192      <h2193        id="section-usage"194        className="text-xl font-semibold text-slate-900 mt-8 mb-4"195      >196        How You Use Qwen Code197      </h2>198      <div className="narrative">199        <p>200          <MarkdownText>{interactionStyle.narrative}</MarkdownText>201        </p>202        {interactionStyle.key_pattern && (203          <div className="key-insight">204            <strong>Key pattern:</strong>{' '}205            <MarkdownText>{interactionStyle.key_pattern}</MarkdownText>206          </div>207        )}208      </div>209 210      <DashboardCards insights={insights} />211      <HeatmapSection heatmap={insights.heatmap} />212    </>213  );214}215 216export function ImpressiveWorkflows({217  qualitative,218  primarySuccess,219  outcomes,220}: {221  qualitative?: QualitativeData;222  primarySuccess: Record<string, number>;223  outcomes: Record<string, number>;224}) {225  const impressiveWorkflows = qualitative?.impressiveWorkflows;226 227  return (228    <>229      <h2230        id="section-wins"231        className="text-xl font-semibold text-slate-900 mt-8 mb-4"232      >233        Impressive Things You Did234      </h2>235      {impressiveWorkflows?.intro && (236        <p className="section-intro">237          <MarkdownText>{impressiveWorkflows.intro}</MarkdownText>238        </p>239      )}240      {impressiveWorkflows && (241        <div className="big-wins">242          {Array.isArray(impressiveWorkflows.impressive_workflows) &&243            impressiveWorkflows.impressive_workflows.map((win, idx) => (244              <div key={idx} className="big-win">245                <div className="big-win-title">{win.title}</div>246                <div className="big-win-desc">247                  <MarkdownText>{win.description}</MarkdownText>248                </div>249              </div>250            ))}251        </div>252      )}253 254      <div255        style={{256          display: 'grid',257          gridTemplateColumns: 'repeat(2, 1fr)',258          gap: '24px',259          marginTop: '24px',260          marginBottom: '24px',261        }}262      >263        {primarySuccess && Object.keys(primarySuccess).length > 0 && (264          <HorizontalBarChart265            data={primarySuccess}266            title="What Helped Most (Qwen's Capabilities)"267            color="#3b82f6"268            allowedKeys={[269              'fast_accurate_search',270              'correct_code_edits',271              'good_explanations',272              'proactive_help',273              'multi_file_changes',274              'good_debugging',275            ]}276          />277        )}278        {outcomes && Object.keys(outcomes).length > 0 && (279          <HorizontalBarChart280            data={outcomes}281            title="Outcomes"282            color="#8b5cf6"283            allowedKeys={[284              'fully_achieved',285              'mostly_achieved',286              'partially_achieved',287              'not_achieved',288              'unclear_from_transcript',289            ]}290          />291        )}292      </div>293    </>294  );295}296 297// Format label for display (capitalize and replace underscores with spaces)298function formatLabel(label: string) {299  if (label === 'unclear_from_transcript') {300    return 'Unclear';301  }302  return label303    .split('_')304    .map((word) => word.charAt(0).toUpperCase() + word.slice(1))305    .join(' ');306}307 308// Horizontal Bar Chart Component309function HorizontalBarChart({310  data,311  title,312  color = '#3b82f6',313  allowedKeys = null,314}: {315  data: Record<string, number>;316  title: string;317  color?: string;318  allowedKeys?: string[] | null;319}) {320  if (!data || Object.keys(data).length === 0) return null;321 322  // Filter and sort entries323  let entries = Object.entries(data).filter(324    ([, count]) => Number.isFinite(count) && count !== 0,325  );326  if (allowedKeys) {327    entries = entries.filter(([key]) => allowedKeys.includes(key));328  }329  entries.sort((a, b) => b[1] - a[1]);330 331  // Limit to at most 10 items332  entries = entries.slice(0, 10);333 334  if (entries.length === 0) return null;335 336  const maxValue = Math.max(...entries.map(([, count]) => count));337 338  return (339    <div340      className="bar-chart-card"341      style={{342        flex: 1,343        minWidth: 0,344        backgroundColor: '#ffffff',345        borderRadius: '12px',346        padding: '20px',347        boxShadow: '0 1px 3px rgba(0, 0, 0, 0.08)',348        border: '1px solid #e2e8f0',349      }}350    >351      <h3352        style={{353          fontSize: '13px',354          fontWeight: 700,355          color: '#64748b',356          marginTop: 0,357          marginBottom: '16px',358          textTransform: 'uppercase',359          letterSpacing: '0.5px',360        }}361      >362        {title}363      </h3>364      <div365        className="bar-chart"366        style={{ display: 'flex', flexDirection: 'column', gap: '10px' }}367      >368        {entries.map(([label, count]) => {369          const percentage = maxValue > 0 ? (count / maxValue) * 100 : 0;370          return (371            <div372              key={label}373              className="bar-row"374              style={{ display: 'flex', alignItems: 'center', gap: '12px' }}375            >376              <div377                className="bar-label"378                style={{379                  width: '130px',380                  fontSize: '13px',381                  color: '#475569',382                  textAlign: 'left',383                  flexShrink: 0,384                  whiteSpace: 'nowrap',385                  overflow: 'hidden',386                  textOverflow: 'ellipsis',387                }}388              >389                {formatLabel(label)}390              </div>391              <div392                className="bar-wrapper"393                style={{394                  flex: 1,395                  display: 'flex',396                  alignItems: 'center',397                  gap: '10px',398                  minWidth: 0,399                }}400              >401                <div402                  className="bar-bg"403                  style={{404                    flex: 1,405                    height: '8px',406                    backgroundColor: '#f1f5f9',407                    borderRadius: '4px',408                    overflow: 'hidden',409                  }}410                >411                  <div412                    className="bar-fill"413                    style={{414                      width: `${percentage}%`,415                      height: '100%',416                      backgroundColor: color,417                      borderRadius: '4px',418                      transition: 'width 0.3s ease',419                    }}420                  />421                </div>422                <span423                  className="bar-value"424                  style={{425                    fontSize: '13px',426                    fontWeight: 600,427                    color: '#475569',428                    minWidth: '24px',429                    textAlign: 'right',430                  }}431                >432                  {count}433                </span>434              </div>435            </div>436          );437        })}438      </div>439    </div>440  );441}442 443export function FrictionPoints({444  qualitative,445  satisfaction,446  friction,447}: {448  qualitative?: QualitativeData;449  satisfaction?: Record<string, number>;450  friction?: Record<string, number>;451}) {452  const frictionPoints = qualitative?.frictionPoints;453 454  return (455    <>456      <h2457        id="section-friction"458        className="text-xl font-semibold text-slate-900 mt-8 mb-4"459      >460        Where Things Go Wrong461      </h2>462      {frictionPoints?.intro && (463        <p className="section-intro">464          <MarkdownText>{frictionPoints.intro}</MarkdownText>465        </p>466      )}467      {frictionPoints && (468        <div className="friction-categories">469          {Array.isArray(frictionPoints.categories) &&470            frictionPoints.categories.map((cat, idx) => (471              <div key={idx} className="friction-category">472                <div className="friction-title">{cat.category}</div>473                <div className="friction-desc">474                  <MarkdownText>{cat.description}</MarkdownText>475                </div>476                {Array.isArray(cat.examples) && cat.examples.length > 0 && (477                  <ul className="friction-examples">478                    {cat.examples.map((ex, i) => (479                      <li key={i}>480                        <MarkdownText>{ex}</MarkdownText>481                      </li>482                    ))}483                  </ul>484                )}485              </div>486            ))}487        </div>488      )}489 490      {/* Facets Data Charts */}491      <div492        style={{493          display: 'grid',494          gridTemplateColumns: 'repeat(2, 1fr)',495          gap: '24px',496          marginTop: '24px',497          marginBottom: '24px',498        }}499      >500        {friction && Object.keys(friction).length > 0 && (501          <HorizontalBarChart502            data={friction}503            title="Primary Friction Types"504            color="#ef4444"505            allowedKeys={[506              'misunderstood_request',507              'wrong_approach',508              'buggy_code',509              'user_rejected_action',510              'excessive_changes',511            ]}512          />513        )}514        {satisfaction && Object.keys(satisfaction).length > 0 && (515          <HorizontalBarChart516            data={satisfaction}517            title="Inferred Satisfaction (model-estimated)"518            color="#10b981"519            allowedKeys={[520              'happy',521              'satisfied',522              'likely_satisfied',523              'dissatisfied',524              'frustrated',525            ]}526          />527        )}528      </div>529    </>530  );531}532 533// Qwen.md Additions Section Component534function QwenMdAdditionsSection({535  additions,536}: {537  additions: NonNullable<538    NonNullable<QualitativeData['improvements']>['Qwen_md_additions']539  >;540}) {541  const [checkedState, setCheckedState] = useState(542    new Array(additions.length).fill(true),543  );544  const [copiedAll, setCopiedAll] = useState(false);545 546  const handleCheckboxChange = (position: number) => {547    const updatedCheckedState = checkedState.map((item, index) =>548      index === position ? !item : item,549    );550    setCheckedState(updatedCheckedState);551  };552 553  const handleCopyAll = () => {554    const textToCopy = additions555      .filter((_, index) => checkedState[index])556      .map((item: { addition: any }) => item.addition)557      .join('\n\n');558 559    if (!textToCopy) return;560 561    navigator.clipboard.writeText(textToCopy).then(() => {562      setCopiedAll(true);563      setTimeout(() => setCopiedAll(false), 2000);564    });565  };566 567  const checkedCount = checkedState.filter(Boolean).length;568 569  return (570    <div className="qwen-md-section">571      <h3>Suggested QWEN.md Additions</h3>572      <p className="text-xs text-slate-500 mb-3">573        Just copy this into Qwen Code to add it to your QWEN.md.574      </p>575 576      <div className="qwen-md-actions" style={{ marginBottom: '12px' }}>577        <button578          className={`copy-all-btn ${copiedAll ? 'copied' : ''}`}579          onClick={handleCopyAll}580          disabled={checkedCount === 0}581        >582          {copiedAll ? 'Copied All!' : `Copy All Checked (${checkedCount})`}583        </button>584      </div>585 586      {additions.map((item, idx) => (587        <div key={idx} className="qwen-md-item">588          <input589            type="checkbox"590            checked={checkedState[idx]}591            onChange={() => handleCheckboxChange(idx)}592            className="cmd-checkbox"593          />594          <div style={{ flex: 1 }}>595            <code className="cmd-code">{item.addition}</code>596            <div className="cmd-why">597              <MarkdownText>{item.why}</MarkdownText>598            </div>599          </div>600          <CopyButton text={item.addition} />601        </div>602      ))}603    </div>604  );605}606 607export function Improvements({608  qualitative,609}: {610  qualitative: QualitativeData;611}) {612  const { improvements } = qualitative;613  if (!improvements) return null;614 615  const hasFeatureSuggestions =616    (Array.isArray(improvements.Qwen_md_additions) &&617      improvements.Qwen_md_additions.length > 0) ||618    (Array.isArray(improvements.features_to_try) &&619      improvements.features_to_try.length > 0);620  const hasUsagePatterns =621    Array.isArray(improvements.usage_patterns) &&622    improvements.usage_patterns.length > 0;623 624  if (!hasFeatureSuggestions && !hasUsagePatterns) return null;625 626  return (627    <>628      {hasFeatureSuggestions && (629        <>630          <h2631            id="section-features"632            className="text-xl font-semibold text-slate-900 mt-8 mb-4"633          >634            Existing Qwen Code Features to Try635          </h2>636 637          {/* QWEN.md Additions */}638          {Array.isArray(improvements.Qwen_md_additions) &&639            improvements.Qwen_md_additions.length > 0 && (640              <QwenMdAdditionsSection641                additions={improvements.Qwen_md_additions}642              />643            )}644 645          <p className="text-xs text-slate-500 mb-3">646            Just copy this into Qwen Code and it&apos;ll set it up for you.647          </p>648 649          {/* Features to Try */}650          <div className="features-section">651            {Array.isArray(improvements.features_to_try) &&652              improvements.features_to_try.map((feat, idx) => (653                <div key={idx} className="feature-card">654                  <div className="feature-title">{feat.feature}</div>655                  <div className="feature-oneliner">656                    <MarkdownText>{feat.one_liner}</MarkdownText>657                  </div>658                  <div className="feature-why">659                    <strong>Why for you:</strong>{' '}660                    <MarkdownText>{feat.why_for_you}</MarkdownText>661                  </div>662                  <div className="feature-examples">663                    <div className="feature-example">664                      <div className="example-code-row">665                        <code className="example-code">666                          {feat.example_code}667                        </code>668                        <CopyButton text={feat.example_code} />669                      </div>670                    </div>671                  </div>672                </div>673              ))}674          </div>675        </>676      )}677 678      {hasUsagePatterns && (679        <>680          <h2681            id="section-patterns"682            className="text-xl font-semibold text-slate-900 mt-8 mb-4"683          >684            New Ways to Use Qwen Code685          </h2>686          <p className="text-xs text-slate-500 mb-3">687            Just copy this into Qwen Code and it&apos;ll walk you through it.688          </p>689 690          <div className="patterns-section">691            {Array.isArray(improvements.usage_patterns) &&692              improvements.usage_patterns.map((pat, idx) => (693                <div key={idx} className="pattern-card">694                  <div className="pattern-title">{pat.title}</div>695                  <div className="pattern-summary">696                    <MarkdownText>{pat.suggestion}</MarkdownText>697                  </div>698                  <div className="pattern-detail">699                    <MarkdownText>{pat.detail}</MarkdownText>700                  </div>701                  <div className="copyable-prompt-section">702                    <div className="prompt-label">Paste into Qwen Code:</div>703                    <div className="copyable-prompt-row">704                      <code className="copyable-prompt">705                        {pat.copyable_prompt}706                      </code>707                      <CopyButton text={pat.copyable_prompt} />708                    </div>709                  </div>710                </div>711              ))}712          </div>713        </>714      )}715    </>716  );717}718 719export function FutureOpportunities({720  qualitative,721}: {722  qualitative: QualitativeData;723}) {724  const { futureOpportunities } = qualitative;725  if (!futureOpportunities) return null;726 727  return (728    <>729      <h2730        id="section-horizon"731        className="text-xl font-semibold text-slate-900 mt-8 mb-4"732      >733        On the Horizon734      </h2>735      {futureOpportunities.intro && (736        <p className="section-intro">737          <MarkdownText>{futureOpportunities.intro}</MarkdownText>738        </p>739      )}740 741      <div className="horizon-section">742        {Array.isArray(futureOpportunities.opportunities) &&743          futureOpportunities.opportunities.map((opp, idx) => (744            <div key={idx} className="horizon-card">745              <div className="horizon-title">{opp.title}</div>746              <div className="horizon-possible">747                <MarkdownText>{opp.whats_possible}</MarkdownText>748              </div>749              <div className="horizon-tip">750                <strong>Getting started:</strong>{' '}751                <MarkdownText>{opp.how_to_try}</MarkdownText>752              </div>753              <div className="pattern-prompt">754                <div className="prompt-label">Paste into Qwen Code:</div>755                <div756                  style={{757                    display: 'flex',758                    alignItems: 'flex-start',759                    gap: '8px',760                  }}761                >762                  <code style={{ flex: 1 }}>{opp.copyable_prompt}</code>763                  <CopyButton text={opp.copyable_prompt} />764                </div>765              </div>766            </div>767          ))}768      </div>769    </>770  );771}772 773export function MemorableMoment({774  qualitative,775}: {776  qualitative: QualitativeData;777}) {778  const { memorableMoment } = qualitative;779  if (!memorableMoment) return null;780 781  return (782    <div className="fun-ending">783      <div className="fun-headline">&quot;{memorableMoment.headline}&quot;</div>784      <div className="fun-detail">785        <MarkdownText>{memorableMoment.detail}</MarkdownText>786      </div>787    </div>788  );789}790