kirin-ri / memo

0 stars 0 forks source link

38 #10

Open kirin-ri opened 8 months ago

kirin-ri commented 8 months ago
// CollapsibleArea.tsx
import React, { useState } from 'react';
import './CollapsibleArea.css';

interface CollapsibleAreaProps {
  title: string;
  items: string[];
}

const CollapsibleArea: React.FC<CollapsibleAreaProps> = ({ title, items }) => {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <div className="collapsible-area">
      <div className="collapsible-header" onClick={() => setIsOpen(!isOpen)}>
        {title}
      </div>
      {isOpen && (
        <div className="collapsible-content">
          <ul>
            {items.map((item, index) => (
              <li key={index}>{item}</li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
};

export default CollapsibleArea;
kirin-ri commented 8 months ago
/* CollapsibleArea.css */
.collapsible-area {
  border: 1px solid #ccc;
  border-radius: 5px;
  margin: 10px;
}

.collapsible-header {
  background-color: #f0f0f0;
  padding: 10px;
  cursor: pointer;
}

.collapsible-content {
  padding: 10px;
}
kirin-ri commented 8 months ago
// ReferenceBar.tsx
import React from 'react';
import CollapsibleArea from './CollapsibleArea';

interface ReferenceBarProps {
  referenceList: string[];
}

const ReferenceBar: React.FC<ReferenceBarProps> = ({ referenceList }) => {
  return (
    <div>
      <CollapsibleArea title="参照列表" items={referenceList} />
    </div>
  );
};

export default ReferenceBar;
kirin-ri commented 8 months ago
// MainComponent.tsx
import React from 'react';
import ReferenceBar from './ReferenceBar';

const MainComponent: React.FC = () => {
  const referenceList = ["Item 1", "Item 2", "Item 3"]; // 你的参照列表

  return (
    <div className="main-component">
      {/* 其他内容 */}
      <ReferenceBar referenceList={referenceList} />
      {/* 其他内容 */}
    </div>
  );
};

export default MainComponent;
kirin-ri commented 8 months ago
import { useContext, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';

import { useCreateReducer } from '@/hooks/useCreateReducer';

import { savePrompts } from '@/utils/app/prompts';

import { OpenAIModels } from '@/types/openai';
import { Prompt } from '@/types/prompt';

import HomeContext from '@/pages/api/home/home.context';

import { PromptFolders } from './components/PromptFolders';
import { PromptbarSettings } from './components/PromptbarSettings';
import { Prompts } from './components/Prompts';

import Sidebar from '../Sidebar';
import PromptbarContext from './PromptBar.context';
import { PromptbarInitialState, initialState } from './Promptbar.state';

import { v4 as uuidv4 } from 'uuid';

const Promptbar = () => {
  const { t } = useTranslation('promptbar');

  const promptBarContextValue = useCreateReducer<PromptbarInitialState>({
    initialState,
  });

  const {
    state: { prompts, defaultModelId, showPromptbar },
    dispatch: homeDispatch,
    handleCreateFolder,
  } = useContext(HomeContext);

  const {
    state: { searchTerm, filteredPrompts },
    dispatch: promptDispatch,
  } = promptBarContextValue;

  const handleTogglePromptbar = () => {
    homeDispatch({ field: 'showPromptbar', value: !showPromptbar });
    localStorage.setItem('showPromptbar', JSON.stringify(!showPromptbar));
  };

  const handleCreatePrompt = () => {
    if (defaultModelId) {
      const newPrompt: Prompt = {
        id: uuidv4(),
        name: `Prompt ${prompts.length + 1}`,
        description: '',
        content: '',
        model: OpenAIModels[defaultModelId],
        folderId: null,
      };

      const updatedPrompts = [...prompts, newPrompt];

      homeDispatch({ field: 'prompts', value: updatedPrompts });

      savePrompts(updatedPrompts);
    }
  };

  const handleDeletePrompt = (prompt: Prompt) => {
    const updatedPrompts = prompts.filter((p) => p.id !== prompt.id);

    homeDispatch({ field: 'prompts', value: updatedPrompts });
    savePrompts(updatedPrompts);
  };

  const handleUpdatePrompt = (prompt: Prompt) => {
    const updatedPrompts = prompts.map((p) => {
      if (p.id === prompt.id) {
        return prompt;
      }

      return p;
    });
    homeDispatch({ field: 'prompts', value: updatedPrompts });

    savePrompts(updatedPrompts);
  };

  const handleDrop = (e: any) => {
    if (e.dataTransfer) {
      const prompt = JSON.parse(e.dataTransfer.getData('prompt'));

      const updatedPrompt = {
        ...prompt,
        folderId: e.target.dataset.folderId,
      };

      handleUpdatePrompt(updatedPrompt);

      e.target.style.background = 'none';
    }
  };

  useEffect(() => {
    if (searchTerm) {
      promptDispatch({
        field: 'filteredPrompts',
        value: prompts.filter((prompt) => {
          const searchable =
            prompt.name.toLowerCase() +
            ' ' +
            prompt.description.toLowerCase() +
            ' ' +
            prompt.content.toLowerCase();
          return searchable.includes(searchTerm.toLowerCase());
        }),
      });
    } else {
      promptDispatch({ field: 'filteredPrompts', value: prompts });
    }
  }, [searchTerm, prompts]);

  return (
    <PromptbarContext.Provider
      value={{
        ...promptBarContextValue,
        handleCreatePrompt,
        handleDeletePrompt,
        handleUpdatePrompt,
      }}
    >
      <Sidebar<Prompt>
        side={'right'}
        isOpen={showPromptbar}
        addItemButtonTitle={t('New prompt')}
        itemComponent={
          <Prompts
            prompts={filteredPrompts.filter((prompt) => !prompt.folderId)}
          />
        }
        folderComponent={<PromptFolders />}
        items={filteredPrompts}
        searchTerm={searchTerm}
        handleSearchTerm={(searchTerm: string) =>
          promptDispatch({ field: 'searchTerm', value: searchTerm })
        }
        toggleOpen={handleTogglePromptbar}
        handleCreateItem={handleCreatePrompt}
        handleCreateFolder={() => handleCreateFolder(t('New folder'), 'prompt')}
        handleDrop={handleDrop}
      />
    </PromptbarContext.Provider>
  );
};

export default Promptbar;
kirin-ri commented 8 months ago
import React, { useState, useEffect, useContext } from 'react';
// 假设您的样式已经由其他全局或父组件CSS文件定义

// 引入HomeContext或者相应的上下文,如果您管理展示状态的逻辑位于全局状态中
import HomeContext from '@/pages/api/home/home.context';

interface Reference {
  id: string;
  title: string;
  description: string;
}

const references: Reference[] = [
  { id: '1', title: '文献1', description: '这是文献1的描述' },
  { id: '2', title: '文献2', description: '这是文献2的描述' },
  // 更多文献...
];

const ReferencesSidebar = () => {
  // 如果是使用全局状态管理展示/收起状态
  const { state: { showReferencesSidebar }, dispatch: homeDispatch } = useContext(HomeContext);

  // 本地组件级别的展示/收起状态,如果不使用全局状态管理
  // const [showReferencesSidebar, setShowReferencesSidebar] = useState(true);

  const handleToggleSidebar = () => {
    // 如果使用全局状态
    homeDispatch({ type: 'TOGGLE_REFERENCES_SIDEBAR' });
    // 如果使用本地状态
    // setShowReferencesSidebar(!showReferencesSidebar);
  };

  return (
    <aside className={`sidebar ${showReferencesSidebar ? 'open' : 'closed'}`}>
      <button onClick={handleToggleSidebar}>
        {showReferencesSidebar ? '收起' : '展示'}
      </button>
      <h2>参考文献</h2>
      <ul>
        {references.map(ref => (
          <li key={ref.id}>
            <h3>{ref.title}</h3>
            <p>{ref.description}</p>
          </li>
        ))}
      </ul>
    </aside>
  );
};

export default ReferencesSidebar;
kirin-ri commented 8 months ago
import React, { useState } from 'react';

interface Reference {
  id: string;
  title: string;
  description: string;
}

const references: Reference[] = [
  { id: '1', title: '文献1', description: '这是文献1的描述' },
  { id: '2', title: '文献2', description: '这是文献2的描述' },
  // 添加更多文献...
];

const ReferencesSidebar = () => {
  // 使用组件状态控制侧边栏显示或隐藏
  const [isSidebarVisible, setIsSidebarVisible] = useState(true);

  // 处理侧边栏显示和隐藏的逻辑
  const handleToggleSidebar = () => {
    setIsSidebarVisible(!isSidebarVisible);
  };

  return (
    <aside className={`sidebar ${isSidebarVisible ? 'open' : 'closed'}`}>
      <button onClick={handleToggleSidebar}>
        {isSidebarVisible ? '收起' : '展示'}
      </button>
      <h2>参考文献</h2>
      <ul>
        {references.map(ref => (
          <li key={ref.id}>
            <h3>{ref.title}</h3>
            <p>{ref.description}</p>
          </li>
        ))}
      </ul>
    </aside>
  );
};

export default ReferencesSidebar;
kirin-ri commented 8 months ago
import React, { useState } from 'react';
import './ReferencesSidebar.css'; // 确保此CSS文件与组件位于同一目录

interface Reference {
  id: string;
  title: string;
  description: string;
}

const references: Reference[] = [
  { id: '1', title: '文献1', description: '这是文献1的描述' },
  { id: '2', title: '文献2', description: '这是文献2的描述' },
  // 添加更多文献...
];

const ReferencesSidebar = () => {
  const [isSidebarVisible, setIsSidebarVisible] = useState(true);

  const handleToggleSidebar = () => {
    setIsSidebarVisible(!isSidebarVisible);
  };

  return (
    <aside className={`sidebar ${isSidebarVisible ? 'open' : 'closed'}`}>
      <button onClick={handleToggleSidebar} className="toggle-button">
        {isSidebarVisible ? '收起' : '展示'}
      </button>
      <h2>参考文献</h2>
      <ul>
        {references.map(ref => (
          <li key={ref.id} className="reference-item">
            <h3>{ref.title}</h3>
            <p>{ref.description}</p>
          </li>
        ))}
      </ul>
    </aside>
  );
};

export default ReferencesSidebar;
kirin-ri commented 8 months ago
.sidebar {
  width: 250px;
  position: fixed;
  right: 0;
  top: 0;
  bottom: 0;
  background-color: #f0f0f0;
  overflow-y: auto;
  padding: 20px;
  transition: transform 0.3s ease;
}

.sidebar.closed {
  transform: translateX(100%);
}

.toggle-button {
  margin-bottom: 15px;
  cursor: pointer;
}

ul {
  list-style-type: none;
  padding: 0;
}

.reference-item {
  background-color: #ffffff;
  margin-bottom: 10px;
  padding: 15px;
  box-shadow: 0 2px 5px rgba(0,0,0,0.2);
  border-radius: 5px;
}

.reference-item h3 {
  margin-top: 0;
}

.reference-item p {
  margin-bottom: 0;
}
kirin-ri commented 8 months ago

error - ./components/Referencebar/ReferencesSidebar.css Global CSS cannot be imported from files other than your Custom . Due to the Global nature of stylesheets, and to avoid conflicts, Please move all first-party global CSS imports to pages/_app.js. Or convert the import to Component-Level CSS (CSS Modules). Read more: https://nextjs.org/docs/messages/css-global Location: components/Referencebar/ReferencesSidebar.tsx

Import trace for requested module: ./components/Referencebar/ReferencesSidebar.css ./components/Referencebar/ReferencesSidebar.tsx ./components/Referencebar/index.ts ./pages/api/home/home.tsx ./pages/api/home/index.ts

kirin-ri commented 8 months ago
import { IconFolderPlus, IconMistOff, IconPlus } from '@tabler/icons-react';
import { ReactNode } from 'react';
import { useTranslation } from 'react-i18next';

import {
  CloseSidebarButton,
  OpenSidebarButton,
} from './components/OpenCloseButton';

import Search from '../Search';

interface Props<T> {
  isOpen: boolean;
  side: 'left' | 'right';
  items: T[];
  toggleOpen: () => void;
}

const ReferenceSidebar = <T,>({
  isOpen,
  side,
  items,
  toggleOpen,
}: Props<T>) => {
  const { t } = useTranslation('promptbar');

  const allowDrop = (e: any) => {
    e.preventDefault();
  };

  const highlightDrop = (e: any) => {
    e.target.style.background = '#343541';
  };

  const removeHighlight = (e: any) => {
    e.target.style.background = 'none';
  };

  return isOpen ? (
    <div>
      <div
        className={`fixed top-0 ${side}-0 z-40 flex h-full w-[260px] flex-none flex-col space-y-2 bg-[#202123] p-2 text-[14px] transition-all sm:relative sm:top-0`}
      >参照リスト
        <div className="flex items-center">
        </div>

      <CloseSidebarButton onClick={toggleOpen} side={side} />
    </div></div>
  ) : (
    <OpenSidebarButton onClick={toggleOpen} side={side} />
  );
};

export default ReferenceSidebar;
kirin-ri commented 8 months ago
import React from 'react';
import { useTranslation } from 'react-i18next';
import { CloseSidebarButton, OpenSidebarButton } from './components/OpenCloseButton';
import styles from './ReferenceSidebar.module.css'; // 确保引入了CSS模块

interface Reference {
  id: string;
  title: string;
  description: string;
}

interface Props<T> {
  isOpen: boolean;
  side: 'left' | 'right';
  items: T[];
  toggleOpen: () => void;
}

// 假设传入的items就是Reference类型的数组
const ReferenceSidebar = ({
  isOpen,
  side,
  items,
  toggleOpen,
}: Props<Reference>) => {
  const { t } = useTranslation('promptbar');

  return isOpen ? (
    <div
      className={`fixed top-0 ${side}-0 z-40 h-full w-[260px] flex-none flex-col p-2 bg-[#202123] text-white transition-all`}
    >
      <div className="flex items-center justify-between">
        <h2 className={styles.sidebarTitle}>{t('referenceList')}</h2>
        <CloseSidebarButton onClick={toggleOpen} side={side} />
      </div>

      <ul className={styles.referenceList}>
        {items.map((ref) => (
          <li key={ref.id} className={styles.referenceItem}>
            <h3 className={styles.referenceTitle}>{ref.title}</h3>
            <p className={styles.referenceDescription}>{ref.description}</p>
          </li>
        ))}
      </ul>
    </div>
  ) : (
    <OpenSidebarButton onClick={toggleOpen} side={side} />
  );
};

export default ReferenceSidebar;
kirin-ri commented 8 months ago
import React from 'react';
import { useTranslation } from 'react-i18next';
import { IconFolderPlus, IconMistOff, IconPlus } from '@tabler/icons-react';
import {
  CloseSidebarButton,
  OpenSidebarButton,
} from './components/OpenCloseButton';
import Search from '../Search';

// 参考文献の型定義
interface Reference {
  id: string;
  title: string;
  description: string;
}

interface Props {
  isOpen: boolean;
  side: 'left' | 'right';
  items: Reference[];
  toggleOpen: () => void;
}

const ReferenceSidebar: React.FC<Props> = ({
  isOpen,
  side,
  items,
  toggleOpen,
}) => {
  const { t } = useTranslation('promptbar');

  return isOpen ? (
    <div
      className={`fixed top-0 ${side}-0 z-40 h-full w-[260px] flex-none flex-col bg-[#202123] p-2 text-[14px] transition-all`}
    >
      <div className="flex items-center justify-between">
        <h2 className="text-white">{t('references')}</h2>
        <CloseSidebarButton onClick={toggleOpen} side={side} />
      </div>

      <Search /> {/* サイドバー内で検索コンポーネントを使用する場合 */}

      <ul className="mt-4 space-y-2 overflow-y-auto">
        {items.map((item) => (
          <li
            key={item.id}
            className="p-2 bg-[#343541] rounded-md text-white"
          >
            <h3>{item.title}</h3>
            <p>{item.description}</p>
          </li>
        ))}
      </ul>
    </div>
  ) : (
    <OpenSidebarButton onClick={toggleOpen} side={side} />
  );
};

export default ReferenceSidebar;
kirin-ri commented 8 months ago

import { IconFolderPlus, IconMistOff, IconPlus } from '@tabler/icons-react'; import { ReactNode } from 'react'; import { useTranslation } from 'react-i18next';

import { CloseSidebarButton, OpenSidebarButton, } from './components/OpenCloseButton';

interface Reference { id: string; title: string; description: string; }

interface Props { isOpen: boolean; side: 'left' | 'right'; items: T[]; toggleOpen: () => void; }

const ReferenceSidebar = ({ isOpen, side, items, toggleOpen, }: Props) => { const { t } = useTranslation('promptbar');

const allowDrop = (e: any) => { e.preventDefault(); };

const highlightDrop = (e: any) => { e.target.style.background = '#343541'; };

const removeHighlight = (e: any) => { e.target.style.background = 'none'; };

const itemsample = [ {id:'1',title:'実績発電原子炉に係る新規制基準の考え方について.pdf',description:'…見直しを行うために「発電用軽水型原子炉の新規制基準に関する検討チーム」(以下「検討チーム」という。)を組織し、発電用軽水型原子炉の新規制基準策定のための検討を開始した。検討チームの会合…'}, {id:'2',title:'実績発電原子炉に係る新規制基準の考え方について.pdf',description:'…見直しを行うために「発電用軽水型原子炉の新規制基準に関する検討チーム」(以下「検討チーム」という。)を組織し、発電用軽水型原子炉の新規制基準策定のための検討を開始した。検討チームの会合…'}, ]

const listItemStyle = { marginBottom: '10px', } return isOpen ? (

参照リスト
    {itemsample.map((item) => (
  • {item.title}

    {item.description}

  • ))}
</div>

) : (

); };

export default ReferenceSidebar; ``

kirin-ri commented 8 months ago
import { IconFolderPlus, IconMistOff, IconPlus } from '@tabler/icons-react';
import { ReactNode } from 'react';
import { useTranslation } from 'react-i18next';

import {
  CloseSidebarButton,
  OpenSidebarButton,
} from './components/OpenCloseButton';

interface Reference {
  id: string;
  title: string;
  description: string;
}

interface Props<T> {
  isOpen: boolean;
  side: 'left' | 'right';
  items: T[];
  toggleOpen: () => void;
}

const ReferenceSidebar = ({
  isOpen,
  side,
  items,
  toggleOpen,
}: Props<Reference>) => {
  const { t } = useTranslation('promptbar');

  const allowDrop = (e: any) => {
    e.preventDefault();
  };

  const highlightDrop = (e: any) => {
    e.target.style.background = '#343541';
  };

  const removeHighlight = (e: any) => {
    e.target.style.background = 'none';
  };

  const itemsample = [
    {id:'1',title:'実績発電原子炉に係る新規制基準の考え方について.pdf',description:'…見直しを行うために「発電用軽水型原子炉の新規制基準に関する検討チーム」(以下「検討チーム」という。)を組織し、発電用軽水型原子炉の新規制基準策定のための検討を開始した。検討チームの会合…'},
    {id:'2',title:'実績発電原子炉に係る新規制基準の考え方について.pdf',description:'…見直しを行うために「発電用軽水型原子炉の新規制基準に関する検討チーム」(以下「検討チーム」という。)を組織し、発電用軽水型原子炉の新規制基準策定のための検討を開始した。検討チームの会合…'},
  ]

  const listItemStyle = {
    marginBottom: '10px',
  }
  return isOpen ? (
    <div>
      <div className={`fixed top-0 ${side}-0 z-40 flex h-full w-[260px] flex-none flex-col space-y-2 bg-[#202123] p-2 text-[14px] transition-all sm:relative sm:top-0`}>
      参照リスト
      <ul>
        {itemsample.map((item) => (
          <li
            key={item.id}
            className="p-2 bg-[#343541] rounded-md text-white"
            style={listItemStyle}
          >
            <h3>{item.title}</h3>
            <p>{item.description}</p>
          </li>
        ))}
      </ul>
        <CloseSidebarButton onClick={toggleOpen} side={side} />
      </div>
    </div>
  ) : (
    <OpenSidebarButton onClick={toggleOpen} side={side} />
  );
};

export default ReferenceSidebar;