Compare commits

...

15 Commits

Author SHA1 Message Date
Joel
5e4689f758 Merge branch 'main' into feat/conversation-pin-op 2023-06-27 18:43:51 +08:00
Joel
0462f09ecc fix: app nav call detail match explore app detail page (#469) 2023-06-27 18:40:24 +08:00
Joel
3580c91be6 Merge branch 'main' into feat/conversation-pin-op 2023-06-27 18:05:28 +08:00
Joel
77f4ca164c chore: reset test paging 2023-06-27 18:04:13 +08:00
zxhlyh
1226d73159 Feat/refact header (#468) 2023-06-27 18:02:01 +08:00
Joel
a5d73a8680 Merge branch 'main' into feat/conversation-pin-op 2023-06-27 17:42:00 +08:00
Joel
21330a4106 fix: new conversatino not set right name 2023-06-27 17:41:37 +08:00
Joel
c00e9608c0 fix: two list scroll ui 2023-06-27 17:27:27 +08:00
Jyong
c67ecff3fe Fix/json format (#465) 2023-06-27 17:15:03 +08:00
Joel
2c01660659 fix: missing vars bind 2023-06-27 17:04:19 +08:00
Joel
3df562d085 feat: i18n and success notify 2023-06-27 16:37:59 +08:00
John Wang
d5b42c09ee fix: template parse error when history include {{any}} (#463) 2023-06-27 16:35:50 +08:00
John Wang
835bf9fd8d fix: template parse error when pre prompt include {{}} (#462) 2023-06-27 15:51:55 +08:00
Joel
04abd4b5c2 feat: converation pin and unpin almost done 2023-06-27 15:41:29 +08:00
John Wang
c720f831af feat: optimize template parse (#460) 2023-06-27 15:30:38 +08:00
53 changed files with 1209 additions and 278 deletions

View File

@@ -3,7 +3,6 @@ from typing import Optional
import langchain
from flask import Flask
from langchain.prompts.base import DEFAULT_FORMATTER_MAPPING
from pydantic import BaseModel
from core.callback_handler.std_out_callback_handler import DifyStdOutCallbackHandler
@@ -22,9 +21,6 @@ hosted_llm_credentials = HostedLLMCredentials()
def init_app(app: Flask):
formatter = OneLineFormatter()
DEFAULT_FORMATTER_MAPPING['f-string'] = formatter.format
if os.environ.get("DEBUG") and os.environ.get("DEBUG").lower() == 'true':
langchain.verbose = True

View File

@@ -23,7 +23,7 @@ from core.memory.read_only_conversation_token_db_buffer_shared_memory import \
from core.memory.read_only_conversation_token_db_string_buffer_shared_memory import \
ReadOnlyConversationTokenDBStringBufferSharedMemory
from core.prompt.prompt_builder import PromptBuilder
from core.prompt.prompt_template import OutLinePromptTemplate
from core.prompt.prompt_template import JinjaPromptTemplate
from core.prompt.prompts import MORE_LIKE_THIS_GENERATE_PROMPT
from models.model import App, AppModelConfig, Account, Conversation, Message
@@ -35,6 +35,8 @@ class Completion:
"""
errors: ProviderTokenNotInitError
"""
query = PromptBuilder.process_template(query)
memory = None
if conversation:
# get memory of conversation (read-only)
@@ -141,18 +143,17 @@ class Completion:
memory: Optional[ReadOnlyConversationTokenDBBufferSharedMemory]) -> \
Tuple[Union[str | List[BaseMessage]], Optional[List[str]]]:
# disable template string in query
query_params = OutLinePromptTemplate.from_template(template=query).input_variables
if query_params:
for query_param in query_params:
if query_param not in inputs:
inputs[query_param] = '{' + query_param + '}'
# query_params = JinjaPromptTemplate.from_template(template=query).input_variables
# if query_params:
# for query_param in query_params:
# if query_param not in inputs:
# inputs[query_param] = '{{' + query_param + '}}'
pre_prompt = PromptBuilder.process_template(pre_prompt) if pre_prompt else pre_prompt
if mode == 'completion':
prompt_template = OutLinePromptTemplate.from_template(
prompt_template = JinjaPromptTemplate.from_template(
template=("""Use the following CONTEXT as your learned knowledge:
[CONTEXT]
{context}
{{context}}
[END CONTEXT]
When answer to user:
@@ -162,16 +163,16 @@ Avoid mentioning that you obtained the information from the context.
And answer according to the language of the user's question.
""" if chain_output else "")
+ (pre_prompt + "\n" if pre_prompt else "")
+ "{query}\n"
+ "{{query}}\n"
)
if chain_output:
inputs['context'] = chain_output
context_params = OutLinePromptTemplate.from_template(template=chain_output).input_variables
if context_params:
for context_param in context_params:
if context_param not in inputs:
inputs[context_param] = '{' + context_param + '}'
# context_params = JinjaPromptTemplate.from_template(template=chain_output).input_variables
# if context_params:
# for context_param in context_params:
# if context_param not in inputs:
# inputs[context_param] = '{{' + context_param + '}}'
prompt_inputs = {k: inputs[k] for k in prompt_template.input_variables if k in inputs}
prompt_content = prompt_template.format(
@@ -195,7 +196,7 @@ And answer according to the language of the user's question.
if pre_prompt:
pre_prompt_inputs = {k: inputs[k] for k in
OutLinePromptTemplate.from_template(template=pre_prompt).input_variables
JinjaPromptTemplate.from_template(template=pre_prompt).input_variables
if k in inputs}
if pre_prompt_inputs:
@@ -205,7 +206,7 @@ And answer according to the language of the user's question.
human_inputs['context'] = chain_output
human_message_prompt += """Use the following CONTEXT as your learned knowledge.
[CONTEXT]
{context}
{{context}}
[END CONTEXT]
When answer to user:
@@ -218,7 +219,7 @@ And answer according to the language of the user's question.
if pre_prompt:
human_message_prompt += pre_prompt
query_prompt = "\nHuman: {query}\nAI: "
query_prompt = "\nHuman: {{query}}\nAI: "
if memory:
# append chat histories
@@ -234,11 +235,11 @@ And answer according to the language of the user's question.
histories = cls.get_history_messages_from_memory(memory, rest_tokens)
# disable template string in query
histories_params = OutLinePromptTemplate.from_template(template=histories).input_variables
if histories_params:
for histories_param in histories_params:
if histories_param not in human_inputs:
human_inputs[histories_param] = '{' + histories_param + '}'
# histories_params = JinjaPromptTemplate.from_template(template=histories).input_variables
# if histories_params:
# for histories_param in histories_params:
# if histories_param not in human_inputs:
# human_inputs[histories_param] = '{{' + histories_param + '}}'
human_message_prompt += "\n\n" + histories

View File

@@ -10,7 +10,7 @@ from core.constant import llm_constant
from core.llm.llm_builder import LLMBuilder
from core.llm.provider.llm_provider_service import LLMProviderService
from core.prompt.prompt_builder import PromptBuilder
from core.prompt.prompt_template import OutLinePromptTemplate
from core.prompt.prompt_template import JinjaPromptTemplate
from events.message_event import message_was_created
from extensions.ext_database import db
from extensions.ext_redis import redis_client
@@ -78,7 +78,7 @@ class ConversationMessageTask:
if self.mode == 'chat':
introduction = self.app_model_config.opening_statement
if introduction:
prompt_template = OutLinePromptTemplate.from_template(template=PromptBuilder.process_template(introduction))
prompt_template = JinjaPromptTemplate.from_template(template=introduction)
prompt_inputs = {k: self.inputs[k] for k in prompt_template.input_variables if k in self.inputs}
try:
introduction = prompt_template.format(**prompt_inputs)
@@ -86,8 +86,7 @@ class ConversationMessageTask:
pass
if self.app_model_config.pre_prompt:
pre_prompt = PromptBuilder.process_template(self.app_model_config.pre_prompt)
system_message = PromptBuilder.to_system_message(pre_prompt, self.inputs)
system_message = PromptBuilder.to_system_message(self.app_model_config.pre_prompt, self.inputs)
system_instruction = system_message.content
llm = LLMBuilder.to_llm(self.tenant_id, self.model_name)
system_instruction_tokens = llm.get_messages_tokens([system_message])
@@ -157,7 +156,7 @@ class ConversationMessageTask:
self.message.message = llm_message.prompt
self.message.message_tokens = message_tokens
self.message.message_unit_price = message_unit_price
self.message.answer = llm_message.completion.strip() if llm_message.completion else ''
self.message.answer = PromptBuilder.process_template(llm_message.completion.strip()) if llm_message.completion else ''
self.message.answer_tokens = answer_tokens
self.message.answer_unit_price = answer_unit_price
self.message.provider_response_latency = llm_message.latency

View File

@@ -36,8 +36,9 @@ class ExcelLoader(BaseLoader):
if keys == []:
keys = list(map(str, row))
else:
row_dict = dict(zip(keys, row))
row_dict = dict(zip(keys, list(map(str, row))))
row_dict = {k: v for k, v in row_dict.items() if v}
data.append(json.dumps(row_dict, ensure_ascii=False))
item = ''.join(f'{k}:{v}\n' for k, v in row_dict.items())
data.append(item)
return [Document(page_content='\n\n'.join(data))]

View File

@@ -134,6 +134,16 @@ class NotionLoader(BaseLoader):
else:
value = property_value[type]
data[property_name] = value
row_dict = {k: v for k, v in data.items() if v}
row_content = ''
for key, value in row_dict.items():
if isinstance(value, dict):
value_dict = {k: v for k, v in value.items() if v}
value_content = ''.join(f'{k}:{v} ' for k, v in value_dict.items())
row_content = row_content + f'{key}:{value_content}\n'
else:
row_content = row_content + f'{key}:{value}\n'
database_content_list.append(row_content)
database_content_list.append(json.dumps(data, ensure_ascii=False))
return "\n\n".join(database_content_list)

View File

@@ -1,5 +1,6 @@
import logging
from langchain import PromptTemplate
from langchain.chat_models.base import BaseChatModel
from langchain.schema import HumanMessage, OutputParserException
@@ -10,7 +11,7 @@ from core.llm.token_calculator import TokenCalculator
from core.prompt.output_parser.rule_config_generator import RuleConfigGeneratorOutputParser
from core.prompt.output_parser.suggested_questions_after_answer import SuggestedQuestionsAfterAnswerOutputParser
from core.prompt.prompt_template import OutLinePromptTemplate
from core.prompt.prompt_template import JinjaPromptTemplate, OutLinePromptTemplate
from core.prompt.prompts import CONVERSATION_TITLE_PROMPT, CONVERSATION_SUMMARY_PROMPT, INTRODUCTION_GENERATE_PROMPT
@@ -91,8 +92,8 @@ class LLMGenerator:
output_parser = SuggestedQuestionsAfterAnswerOutputParser()
format_instructions = output_parser.get_format_instructions()
prompt = OutLinePromptTemplate(
template="{histories}\n{format_instructions}\nquestions:\n",
prompt = JinjaPromptTemplate(
template="{{histories}}\n{{format_instructions}}\nquestions:\n",
input_variables=["histories"],
partial_variables={"format_instructions": format_instructions}
)

View File

@@ -3,13 +3,13 @@ import re
from langchain.prompts import SystemMessagePromptTemplate, HumanMessagePromptTemplate, AIMessagePromptTemplate
from langchain.schema import BaseMessage
from core.prompt.prompt_template import OutLinePromptTemplate
from core.prompt.prompt_template import JinjaPromptTemplate
class PromptBuilder:
@classmethod
def to_system_message(cls, prompt_content: str, inputs: dict) -> BaseMessage:
prompt_template = OutLinePromptTemplate.from_template(prompt_content)
prompt_template = JinjaPromptTemplate.from_template(prompt_content)
system_prompt_template = SystemMessagePromptTemplate(prompt=prompt_template)
prompt_inputs = {k: inputs[k] for k in system_prompt_template.input_variables if k in inputs}
system_message = system_prompt_template.format(**prompt_inputs)
@@ -17,7 +17,7 @@ class PromptBuilder:
@classmethod
def to_ai_message(cls, prompt_content: str, inputs: dict) -> BaseMessage:
prompt_template = OutLinePromptTemplate.from_template(prompt_content)
prompt_template = JinjaPromptTemplate.from_template(prompt_content)
ai_prompt_template = AIMessagePromptTemplate(prompt=prompt_template)
prompt_inputs = {k: inputs[k] for k in ai_prompt_template.input_variables if k in inputs}
ai_message = ai_prompt_template.format(**prompt_inputs)
@@ -25,13 +25,14 @@ class PromptBuilder:
@classmethod
def to_human_message(cls, prompt_content: str, inputs: dict) -> BaseMessage:
prompt_template = OutLinePromptTemplate.from_template(prompt_content)
prompt_template = JinjaPromptTemplate.from_template(prompt_content)
human_prompt_template = HumanMessagePromptTemplate(prompt=prompt_template)
human_message = human_prompt_template.format(**inputs)
return human_message
@classmethod
def process_template(cls, template: str):
processed_template = re.sub(r'\{([a-zA-Z_]\w+?)\}', r'\1', template)
processed_template = re.sub(r'\{\{([a-zA-Z_]\w+?)\}\}', r'{\1}', processed_template)
processed_template = re.sub(r'\{{2}(.+)\}{2}', r'{\1}', template)
# processed_template = re.sub(r'\{([a-zA-Z_]\w+?)\}', r'\1', template)
# processed_template = re.sub(r'\{\{([a-zA-Z_]\w+?)\}\}', r'{\1}', processed_template)
return processed_template

View File

@@ -1,10 +1,34 @@
import re
from typing import Any
from jinja2 import Environment, meta
from langchain import PromptTemplate
from langchain.formatting import StrictFormatter
class JinjaPromptTemplate(PromptTemplate):
template_format: str = "jinja2"
"""The format of the prompt template. Options are: 'f-string', 'jinja2'."""
@classmethod
def from_template(cls, template: str, **kwargs: Any) -> PromptTemplate:
"""Load a prompt template from a template."""
env = Environment()
template = template.replace("{{}}", "{}")
ast = env.parse(template)
input_variables = meta.find_undeclared_variables(ast)
if "partial_variables" in kwargs:
partial_variables = kwargs["partial_variables"]
input_variables = {
var for var in input_variables if var not in partial_variables
}
return cls(
input_variables=list(sorted(input_variables)), template=template, **kwargs
)
class OutLinePromptTemplate(PromptTemplate):
@classmethod
def from_template(cls, template: str, **kwargs: Any) -> PromptTemplate:
@@ -16,6 +40,24 @@ class OutLinePromptTemplate(PromptTemplate):
input_variables=list(sorted(input_variables)), template=template, **kwargs
)
def format(self, **kwargs: Any) -> str:
"""Format the prompt with the inputs.
Args:
kwargs: Any arguments to be passed to the prompt template.
Returns:
A formatted string.
Example:
.. code-block:: python
prompt.format(variable1="foo")
"""
kwargs = self._merge_partial_and_user_variables(**kwargs)
return OneLineFormatter().format(self.template, **kwargs)
class OneLineFormatter(StrictFormatter):
def parse(self, format_string):

View File

@@ -1,5 +1,5 @@
CONVERSATION_TITLE_PROMPT = (
"Human:{query}\n-----\n"
"Human:{{query}}\n-----\n"
"Help me summarize the intent of what the human said and provide a title, the title should not exceed 20 words.\n"
"If the human said is conducted in Chinese, you should return a Chinese title.\n"
"If the human said is conducted in English, you should return an English title.\n"
@@ -19,7 +19,7 @@ CONVERSATION_SUMMARY_PROMPT = (
INTRODUCTION_GENERATE_PROMPT = (
"I am designing a product for users to interact with an AI through dialogue. "
"The Prompt given to the AI before the conversation is:\n\n"
"```\n{prompt}\n```\n\n"
"```\n{{prompt}}\n```\n\n"
"Please generate a brief introduction of no more than 50 words that greets the user, based on this Prompt. "
"Do not reveal the developer's motivation or deep logic behind the Prompt, "
"but focus on building a relationship with the user:\n"
@@ -27,13 +27,13 @@ INTRODUCTION_GENERATE_PROMPT = (
MORE_LIKE_THIS_GENERATE_PROMPT = (
"-----\n"
"{original_completion}\n"
"{{original_completion}}\n"
"-----\n\n"
"Please use the above content as a sample for generating the result, "
"and include key information points related to the original sample in the result. "
"Try to rephrase this information in different ways and predict according to the rules below.\n\n"
"-----\n"
"{prompt}\n"
"{{prompt}}\n"
)
SUGGESTED_QUESTIONS_AFTER_ANSWER_INSTRUCTION_PROMPT = (

View File

@@ -0,0 +1,3 @@
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.3625 8H2.6958M2.6958 8L6.6958 12M2.6958 8L6.6958 4" stroke="#155EEF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 251 B

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.6666 4.85185L7.99998 8M7.99998 8L2.33331 4.85185M7.99998 8L8 14.3333M14 10.7057V5.29431C14 5.06588 14 4.95167 13.9663 4.8498C13.9366 4.75969 13.8879 4.67696 13.8236 4.60717C13.7509 4.52828 13.651 4.47281 13.4514 4.36188L8.51802 1.62114C8.32895 1.5161 8.23442 1.46358 8.1343 1.44299C8.0457 1.42477 7.95431 1.42477 7.8657 1.44299C7.76559 1.46358 7.67105 1.5161 7.48198 1.62114L2.54865 4.36188C2.34896 4.47281 2.24912 4.52828 2.17642 4.60717C2.11211 4.67697 2.06343 4.75969 2.03366 4.84981C2 4.95167 2 5.06588 2 5.29431V10.7057C2 10.9341 2 11.0484 2.03366 11.1502C2.06343 11.2403 2.11211 11.3231 2.17642 11.3929C2.24912 11.4718 2.34897 11.5272 2.54865 11.6382L7.48198 14.3789C7.67105 14.4839 7.76559 14.5365 7.8657 14.557C7.95431 14.5753 8.0457 14.5753 8.1343 14.557C8.23442 14.5365 8.32895 14.4839 8.51802 14.3789L13.4514 11.6382C13.651 11.5272 13.7509 11.4718 13.8236 11.3929C13.8879 11.3231 13.9366 11.2403 13.9663 11.1502C14 11.0484 14 10.9341 14 10.7057Z" stroke="#667085" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,3 @@
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.5 3.33337C14.5 4.43794 11.8137 5.33337 8.5 5.33337C5.18629 5.33337 2.5 4.43794 2.5 3.33337M14.5 3.33337C14.5 2.2288 11.8137 1.33337 8.5 1.33337C5.18629 1.33337 2.5 2.2288 2.5 3.33337M14.5 3.33337V12.6667C14.5 13.7734 11.8333 14.6667 8.5 14.6667C5.16667 14.6667 2.5 13.7734 2.5 12.6667V3.33337M14.5 8.00004C14.5 9.10671 11.8333 10 8.5 10C5.16667 10 2.5 9.10671 2.5 8.00004" stroke="#667085" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 575 B

View File

@@ -0,0 +1,10 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="puzzle-piece-01" clip-path="url(#clip0_6770_9698)">
<path id="Icon" d="M4.99992 3.00004C4.99992 2.07957 5.74611 1.33337 6.66659 1.33337C7.58706 1.33337 8.33325 2.07957 8.33325 3.00004V4.00004H8.99992C9.9318 4.00004 10.3977 4.00004 10.7653 4.15228C11.2553 4.35527 11.6447 4.74462 11.8477 5.23467C11.9999 5.60222 11.9999 6.06816 11.9999 7.00004H12.9999C13.9204 7.00004 14.6666 7.74623 14.6666 8.66671C14.6666 9.58718 13.9204 10.3334 12.9999 10.3334H11.9999V11.4667C11.9999 12.5868 11.9999 13.1469 11.7819 13.5747C11.5902 13.951 11.2842 14.257 10.9079 14.4487C10.4801 14.6667 9.92002 14.6667 8.79992 14.6667H8.33325V13.5C8.33325 12.6716 7.66168 12 6.83325 12C6.00483 12 5.33325 12.6716 5.33325 13.5V14.6667H4.53325C3.41315 14.6667 2.85309 14.6667 2.42527 14.4487C2.04895 14.257 1.74299 13.951 1.55124 13.5747C1.33325 13.1469 1.33325 12.5868 1.33325 11.4667V10.3334H2.33325C3.25373 10.3334 3.99992 9.58718 3.99992 8.66671C3.99992 7.74623 3.25373 7.00004 2.33325 7.00004H1.33325C1.33325 6.06816 1.33325 5.60222 1.48549 5.23467C1.68848 4.74462 2.07783 4.35527 2.56789 4.15228C2.93543 4.00004 3.40137 4.00004 4.33325 4.00004H4.99992V3.00004Z" stroke="#667085" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_6770_9698">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,10 @@
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="grid-01">
<g id="Icon">
<path d="M6.1 2H3.56667C3.1933 2 3.00661 2 2.86401 2.07266C2.73856 2.13658 2.63658 2.23856 2.57266 2.36401C2.5 2.50661 2.5 2.6933 2.5 3.06667V5.6C2.5 5.97337 2.5 6.16005 2.57266 6.30266C2.63658 6.4281 2.73856 6.53009 2.86401 6.594C3.00661 6.66667 3.1933 6.66667 3.56667 6.66667H6.1C6.47337 6.66667 6.66005 6.66667 6.80266 6.594C6.9281 6.53009 7.03009 6.4281 7.094 6.30266C7.16667 6.16005 7.16667 5.97337 7.16667 5.6V3.06667C7.16667 2.6933 7.16667 2.50661 7.094 2.36401C7.03009 2.23856 6.9281 2.13658 6.80266 2.07266C6.66005 2 6.47337 2 6.1 2Z" stroke="#667085" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.4333 2H10.9C10.5266 2 10.3399 2 10.1973 2.07266C10.0719 2.13658 9.96991 2.23856 9.906 2.36401C9.83333 2.50661 9.83333 2.6933 9.83333 3.06667V5.6C9.83333 5.97337 9.83333 6.16005 9.906 6.30266C9.96991 6.4281 10.0719 6.53009 10.1973 6.594C10.3399 6.66667 10.5266 6.66667 10.9 6.66667H13.4333C13.8067 6.66667 13.9934 6.66667 14.136 6.594C14.2614 6.53009 14.3634 6.4281 14.4273 6.30266C14.5 6.16005 14.5 5.97337 14.5 5.6V3.06667C14.5 2.6933 14.5 2.50661 14.4273 2.36401C14.3634 2.23856 14.2614 2.13658 14.136 2.07266C13.9934 2 13.8067 2 13.4333 2Z" stroke="#667085" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.4333 9.33333H10.9C10.5266 9.33333 10.3399 9.33333 10.1973 9.406C10.0719 9.46991 9.96991 9.5719 9.906 9.69734C9.83333 9.83995 9.83333 10.0266 9.83333 10.4V12.9333C9.83333 13.3067 9.83333 13.4934 9.906 13.636C9.96991 13.7614 10.0719 13.8634 10.1973 13.9273C10.3399 14 10.5266 14 10.9 14H13.4333C13.8067 14 13.9934 14 14.136 13.9273C14.2614 13.8634 14.3634 13.7614 14.4273 13.636C14.5 13.4934 14.5 13.3067 14.5 12.9333V10.4C14.5 10.0266 14.5 9.83995 14.4273 9.69734C14.3634 9.5719 14.2614 9.46991 14.136 9.406C13.9934 9.33333 13.8067 9.33333 13.4333 9.33333Z" stroke="#667085" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.1 9.33333H3.56667C3.1933 9.33333 3.00661 9.33333 2.86401 9.406C2.73856 9.46991 2.63658 9.5719 2.57266 9.69734C2.5 9.83995 2.5 10.0266 2.5 10.4V12.9333C2.5 13.3067 2.5 13.4934 2.57266 13.636C2.63658 13.7614 2.73856 13.8634 2.86401 13.9273C3.00661 14 3.1933 14 3.56667 14H6.1C6.47337 14 6.66005 14 6.80266 13.9273C6.9281 13.8634 7.03009 13.7614 7.094 13.636C7.16667 13.4934 7.16667 13.3067 7.16667 12.9333V10.4C7.16667 10.0266 7.16667 9.83995 7.094 9.69734C7.03009 9.5719 6.9281 9.46991 6.80266 9.406C6.66005 9.33333 6.47337 9.33333 6.1 9.33333Z" stroke="#667085" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -0,0 +1,5 @@
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.29782 0.790031C8.12061 0.753584 7.93783 0.753584 7.76062 0.790031C7.55577 0.832161 7.37268 0.934712 7.22712 1.01624L7.18744 1.03841C6.01215 1.69134 4.02394 2.79644 2.90301 3.41952C2.63085 3.5708 2.49477 3.64644 2.44929 3.74641C2.40965 3.83357 2.4094 3.93356 2.4486 4.02091C2.49357 4.12111 2.62938 4.19751 2.90101 4.3503L7.76772 7.08785C7.8631 7.1415 7.91079 7.16832 7.96135 7.17884C8.0061 7.18814 8.05229 7.18814 8.09703 7.17884C8.1476 7.16832 8.19529 7.1415 8.29067 7.08785L13.1574 4.35029C13.429 4.1975 13.5649 4.12111 13.6098 4.02091C13.649 3.93355 13.6488 3.83356 13.6091 3.74641C13.5637 3.64644 13.4276 3.57079 13.1554 3.41951C12.0345 2.79644 10.0463 1.69134 8.871 1.03841L8.83132 1.01624C8.68576 0.934713 8.50267 0.832161 8.29782 0.790031Z" fill="#155EEF"/>
<path d="M14.6932 5.92676C14.6929 5.62787 14.6928 5.47842 14.6297 5.39117C14.5748 5.31504 14.4902 5.26564 14.3969 5.25511C14.2899 5.24305 14.1594 5.31646 13.8984 5.46329L8.96774 8.23679C8.86877 8.29246 8.81928 8.3203 8.78326 8.35968C8.75139 8.39452 8.72729 8.43573 8.71254 8.48059C8.69588 8.53129 8.69588 8.58807 8.69588 8.70163V14.1518C8.69588 14.4499 8.69588 14.599 8.75856 14.6862C8.81326 14.7623 8.89744 14.8118 8.9905 14.8227C9.09716 14.8352 9.22706 14.763 9.48688 14.6188C10.5978 14.0019 12.6169 12.8807 13.8043 12.221L13.8464 12.1977C14.0005 12.1128 14.1943 12.0061 14.343 11.8447C14.4717 11.7051 14.569 11.5397 14.6286 11.3594C14.6975 11.1509 14.6966 10.9298 14.696 10.7538L14.6959 10.7058C14.6959 9.39704 14.6942 7.17087 14.6932 5.92676Z" fill="#155EEF"/>
<path d="M6.57155 14.6187C6.83137 14.763 6.96128 14.8352 7.06793 14.8227C7.16099 14.8118 7.24518 14.7623 7.29987 14.6862C7.36255 14.599 7.36255 14.4499 7.36255 14.1518V8.70166C7.36255 8.5881 7.36255 8.53132 7.34589 8.48062C7.33114 8.43576 7.30704 8.39455 7.27517 8.35971C7.23915 8.32033 7.18966 8.29249 7.09069 8.23682L2.16004 5.4633C1.89902 5.31648 1.76851 5.24306 1.66154 5.25513C1.56823 5.26565 1.48367 5.31506 1.42869 5.39118C1.36566 5.47844 1.36553 5.62789 1.36528 5.92678C1.36424 7.17088 1.36255 9.39704 1.36255 10.7058L1.36243 10.7538C1.36179 10.9298 1.36099 11.1509 1.42986 11.3594C1.48941 11.5397 1.58676 11.7051 1.71539 11.8447C1.86417 12.0061 2.0579 12.1128 2.21199 12.1977L2.2541 12.221C3.44156 12.8807 5.46065 14.0019 6.57155 14.6187Z" fill="#155EEF"/>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,5 @@
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.1956 4.66669V3.33335C15.1956 2.76539 14.8497 2.33041 14.4701 2.03126C14.083 1.72618 13.5641 1.48059 12.9824 1.28668C11.812 0.896551 10.2375 0.666687 8.52897 0.666687C6.8204 0.666687 5.24591 0.896551 4.07551 1.28668C3.4938 1.48059 2.97495 1.72618 2.58783 2.03126C2.20823 2.33041 1.8623 2.76539 1.8623 3.33335V4.66669C1.8623 5.23294 2.20443 5.66805 2.58368 5.96857C2.96958 6.27436 3.48705 6.52014 4.06786 6.71405C5.23637 7.10415 6.81113 7.33335 8.52897 7.33335C10.2468 7.33335 11.8216 7.10415 12.9901 6.71405C13.5709 6.52014 14.0884 6.27436 14.4743 5.96857C14.8535 5.66805 15.1956 5.23294 15.1956 4.66669ZM3.19564 3.33353C3.19564 3.33353 3.19576 3.33725 3.19767 3.34355C3.19994 3.35098 3.20552 3.36565 3.21902 3.38764C3.24732 3.43374 3.30502 3.50304 3.41313 3.58824C3.63325 3.76171 3.99308 3.94709 4.49715 4.11511C5.49832 4.44884 6.92383 4.66669 8.52897 4.66669C10.1341 4.66669 11.5596 4.44884 12.5608 4.11511C13.0649 3.94709 13.4247 3.76171 13.6448 3.58824C13.7529 3.50304 13.8106 3.43374 13.8389 3.38764C13.8524 3.36565 13.858 3.35098 13.8603 3.34355C13.8622 3.33716 13.8623 3.33335 13.8623 3.33335C13.8623 3.33335 13.8624 3.33006 13.8603 3.32316C13.858 3.31573 13.8524 3.30105 13.8389 3.27907C13.8106 3.23297 13.7529 3.16367 13.6448 3.07847C13.4247 2.905 13.0649 2.71962 12.5608 2.5516C11.5596 2.21787 10.1341 2.00002 8.52897 2.00002C6.92383 2.00002 5.49832 2.21787 4.49715 2.5516C3.99308 2.71962 3.63325 2.905 3.41313 3.07847C3.30502 3.16367 3.24732 3.23297 3.21902 3.27907C3.20552 3.30105 3.19994 3.31573 3.19767 3.32316C3.19563 3.32988 3.19564 3.33353 3.19564 3.33353Z" fill="#155EEF"/>
<path d="M14.9234 7.00002C14.8447 7.00002 14.7705 7.03473 14.7155 7.09102C14.6407 7.16749 14.5613 7.23785 14.4802 7.30206C14.0939 7.60785 13.5759 7.85363 12.9945 8.04753C11.8249 8.43764 10.2485 8.66684 8.52896 8.66684C6.8094 8.66684 5.23307 8.43764 4.06339 8.04753C3.48201 7.85363 2.96401 7.60785 2.57773 7.30206C2.49661 7.23784 2.41719 7.16749 2.34244 7.09101C2.28743 7.03473 2.21322 7.00002 2.13452 7.00002C1.98418 7.00002 1.8623 7.12189 1.8623 7.27223V8.66669C1.8623 9.23294 2.20443 9.66805 2.58368 9.96857C2.96958 10.2744 3.48705 10.5201 4.06786 10.714C5.23637 11.1041 6.81113 11.3334 8.52897 11.3334C10.2468 11.3334 11.8216 11.1041 12.9901 10.714C13.5709 10.5201 14.0884 10.2744 14.4743 9.96857C14.8535 9.66805 15.1956 9.23294 15.1956 8.66669V7.27224C15.1956 7.1219 15.0738 7.00002 14.9234 7.00002Z" fill="#155EEF"/>
<path d="M14.9234 11C14.8447 11 14.7705 11.0347 14.7155 11.091C14.6407 11.1675 14.5613 11.2378 14.4802 11.3021C14.0939 11.6079 13.5759 11.8536 12.9945 12.0475C11.8249 12.4376 10.2485 12.6668 8.52896 12.6668C6.8094 12.6668 5.23307 12.4376 4.06339 12.0475C3.48201 11.8536 2.96401 11.6079 2.57773 11.3021C2.49661 11.2378 2.41719 11.1675 2.34244 11.091C2.28743 11.0347 2.21322 11 2.13452 11C1.98418 11 1.8623 11.1219 1.8623 11.2722V12.6667C1.8623 13.2329 2.20443 13.668 2.58368 13.9686C2.96958 14.2744 3.48705 14.5201 4.06786 14.714C5.23637 15.1041 6.81113 15.3334 8.52897 15.3334C10.2468 15.3334 11.8216 15.1041 12.9901 14.714C13.5709 14.5201 14.0884 14.2744 14.4743 13.9686C14.8535 13.668 15.1956 13.2329 15.1956 12.6667V11.2722C15.1956 11.1219 15.0738 11 14.9234 11Z" fill="#155EEF"/>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,5 @@
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="puzzle-piece-01">
<path id="Solid" fill-rule="evenodd" clip-rule="evenodd" d="M4.83333 2.99999C4.83333 1.71133 5.878 0.666656 7.16667 0.666656C8.45533 0.666656 9.5 1.71133 9.5 2.99999V3.33332L9.52285 3.33332C9.96938 3.33332 10.338 3.33331 10.6397 3.3539C10.9525 3.37525 11.2419 3.42093 11.5205 3.53631C12.1739 3.80696 12.693 4.32609 12.9637 4.9795C13.0791 5.25804 13.1247 5.54744 13.1461 5.8603C13.1558 6.0027 13.1609 6.15998 13.1636 6.33332H13.5C14.7887 6.33332 15.8333 7.37799 15.8333 8.66666C15.8333 9.95532 14.7887 11 13.5 11H13.1667V11.4942C13.1667 12.0308 13.1667 12.4737 13.1372 12.8345C13.1066 13.2093 13.0409 13.5537 12.876 13.8773C12.6204 14.3791 12.2124 14.787 11.7106 15.0427C11.3871 15.2075 11.0426 15.2732 10.6679 15.3039C10.3071 15.3333 9.86419 15.3333 9.32755 15.3333H8.83333C8.46514 15.3333 8.16667 15.0348 8.16667 14.6667V13.5C8.16667 13.0398 7.79357 12.6667 7.33333 12.6667C6.8731 12.6667 6.5 13.0398 6.5 13.5V14.6667C6.5 15.0348 6.20152 15.3333 5.83333 15.3333H5.00578C4.46914 15.3333 4.02624 15.3333 3.66545 15.3039C3.29072 15.2732 2.94625 15.2075 2.62269 15.0427C2.12093 14.787 1.71298 14.3791 1.45732 13.8773C1.29246 13.5537 1.22675 13.2093 1.19613 12.8345C1.16665 12.4737 1.16666 12.0308 1.16667 11.4942L1.16667 10.3333C1.16667 9.96513 1.46514 9.66666 1.83333 9.66666H2.83333C3.38562 9.66666 3.83333 9.21894 3.83333 8.66666C3.83333 8.11437 3.38562 7.66666 2.83333 7.66666H1.83333C1.46514 7.66666 1.16667 7.36818 1.16667 6.99999L1.16667 6.97715C1.16666 6.53062 1.16666 6.16204 1.18724 5.8603C1.20859 5.54744 1.25428 5.25804 1.36965 4.9795C1.64031 4.32609 2.15944 3.80696 2.81284 3.53631C3.09139 3.42093 3.38078 3.37525 3.69364 3.3539C3.99538 3.33331 4.36396 3.33332 4.81048 3.33332L4.83333 3.33332L4.83333 2.99999Z" fill="#155EEF"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,10 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="grid-01">
<g id="Solid">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.04545 1.33338C3.90407 1.33348 4.76437 1.33348 5.62131 1.33338C5.78956 1.33336 5.95343 1.33334 6.0922 1.34467C6.24459 1.35713 6.42442 1.3865 6.60536 1.4787C6.85625 1.60653 7.06022 1.81051 7.18805 2.06139C7.28025 2.24234 7.30963 2.42216 7.32208 2.57456C7.33342 2.71333 7.3334 2.8772 7.33338 3.04546V5.6213C7.3334 5.78956 7.33342 5.95342 7.32208 6.0922C7.30963 6.24459 7.28025 6.42442 7.18805 6.60536C7.06022 6.85625 6.85625 7.06022 6.60536 7.18805C6.42442 7.28025 6.24459 7.30963 6.0922 7.32208C5.95342 7.33342 5.78956 7.3334 5.6213 7.33338H3.04546C2.8772 7.3334 2.71333 7.33342 2.57456 7.32208C2.42216 7.30963 2.24234 7.28025 2.06139 7.18805C1.81051 7.06022 1.60653 6.85625 1.4787 6.60536C1.3865 6.42442 1.35713 6.24459 1.34467 6.0922C1.33334 5.95343 1.33336 5.78956 1.33338 5.62131C1.33338 5.61423 1.33338 5.60714 1.33338 5.60004V3.06671C1.33338 3.05962 1.33338 3.05253 1.33338 3.04545C1.33336 2.87719 1.33334 2.71333 1.34467 2.57456C1.35713 2.42216 1.3865 2.24234 1.4787 2.06139C1.60653 1.81051 1.81051 1.60653 2.06139 1.4787C2.24234 1.3865 2.42216 1.35713 2.57456 1.34467C2.71333 1.33334 2.87719 1.33336 3.04545 1.33338Z" fill="#155EEF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.04545 8.66671C3.90407 8.66682 4.76437 8.66682 5.62131 8.66671C5.78956 8.66669 5.95343 8.66667 6.0922 8.67801C6.24459 8.69046 6.42442 8.71984 6.60536 8.81204C6.85625 8.93987 7.06022 9.14384 7.18805 9.39472C7.28025 9.57567 7.30963 9.7555 7.32208 9.90789C7.33342 10.0467 7.3334 10.2105 7.33338 10.3788V12.9546C7.3334 13.1229 7.33342 13.2868 7.32208 13.4255C7.30963 13.5779 7.28025 13.7577 7.18805 13.9387C7.06022 14.1896 6.85625 14.3936 6.60536 14.5214C6.42442 14.6136 6.24459 14.643 6.0922 14.6554C5.95342 14.6668 5.78956 14.6667 5.6213 14.6667H3.04546C2.8772 14.6667 2.71333 14.6668 2.57456 14.6554C2.42216 14.643 2.24234 14.6136 2.06139 14.5214C1.81051 14.3936 1.60653 14.1896 1.4787 13.9387C1.3865 13.7577 1.35713 13.5779 1.34467 13.4255C1.33334 13.2868 1.33336 13.1229 1.33338 12.9546C1.33338 12.9476 1.33338 12.9405 1.33338 12.9334V10.4C1.33338 10.3929 1.33338 10.3859 1.33338 10.3788C1.33336 10.2105 1.33334 10.0467 1.34467 9.90789C1.35713 9.7555 1.3865 9.57567 1.4787 9.39472C1.60653 9.14384 1.81051 8.93987 2.06139 8.81204C2.24234 8.71984 2.42216 8.69046 2.57456 8.67801C2.71333 8.66667 2.87719 8.66669 3.04545 8.66671Z" fill="#155EEF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.3788 1.33338C11.2374 1.33348 12.0977 1.33348 12.9546 1.33338C13.1229 1.33336 13.2868 1.33334 13.4255 1.34467C13.5779 1.35713 13.7577 1.3865 13.9387 1.4787C14.1896 1.60653 14.3936 1.81051 14.5214 2.06139C14.6136 2.24234 14.643 2.42216 14.6554 2.57456C14.6668 2.71333 14.6667 2.8772 14.6667 3.04546V5.6213C14.6667 5.78956 14.6668 5.95342 14.6554 6.0922C14.643 6.24459 14.6136 6.42442 14.5214 6.60536C14.3936 6.85625 14.1896 7.06022 13.9387 7.18805C13.7577 7.28025 13.5779 7.30963 13.4255 7.32208C13.2868 7.33342 13.1229 7.3334 12.9546 7.33338H10.3788C10.2105 7.3334 10.0467 7.33342 9.90789 7.32208C9.7555 7.30963 9.57567 7.28025 9.39472 7.18805C9.14384 7.06022 8.93987 6.85625 8.81204 6.60536C8.71984 6.42442 8.69046 6.24459 8.67801 6.0922C8.66667 5.95343 8.66669 5.78956 8.66671 5.62131C8.66671 5.61423 8.66671 5.60714 8.66671 5.60004V3.06671C8.66671 3.05962 8.66671 3.05253 8.66671 3.04545C8.66669 2.87719 8.66667 2.71333 8.67801 2.57456C8.69046 2.42216 8.71984 2.24234 8.81204 2.06139C8.93987 1.81051 9.14384 1.60653 9.39472 1.4787C9.57567 1.3865 9.7555 1.35713 9.90789 1.34467C10.0467 1.33334 10.2105 1.33336 10.3788 1.33338Z" fill="#155EEF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.3788 8.66671C11.2374 8.66682 12.0977 8.66682 12.9546 8.66671C13.1229 8.66669 13.2868 8.66667 13.4255 8.67801C13.5779 8.69046 13.7577 8.71984 13.9387 8.81204C14.1896 8.93987 14.3936 9.14384 14.5214 9.39472C14.6136 9.57567 14.643 9.7555 14.6554 9.90789C14.6668 10.0467 14.6667 10.2105 14.6667 10.3788V12.9546C14.6667 13.1229 14.6668 13.2868 14.6554 13.4255C14.643 13.5779 14.6136 13.7577 14.5214 13.9387C14.3936 14.1896 14.1896 14.3936 13.9387 14.5214C13.7577 14.6136 13.5779 14.643 13.4255 14.6554C13.2868 14.6668 13.1229 14.6667 12.9546 14.6667H10.3788C10.2105 14.6667 10.0467 14.6668 9.90789 14.6554C9.7555 14.643 9.57567 14.6136 9.39472 14.5214C9.14384 14.3936 8.93987 14.1896 8.81204 13.9387C8.71984 13.7577 8.69046 13.5779 8.67801 13.4255C8.66667 13.2868 8.66669 13.1229 8.66671 12.9546C8.66671 12.9476 8.66671 12.9405 8.66671 12.9334V10.4C8.66671 10.3929 8.66671 10.3859 8.66671 10.3788C8.66669 10.2105 8.66667 10.0467 8.67801 9.90789C8.69046 9.7555 8.71984 9.57567 8.81204 9.39472C8.93987 9.14384 9.14384 8.93987 9.39472 8.81204C9.57567 8.71984 9.7555 8.69046 9.90789 8.67801C10.0467 8.66667 10.2105 8.66669 10.3788 8.66671Z" fill="#155EEF"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -0,0 +1,29 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "17",
"height": "16",
"viewBox": "0 0 17 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M13.3625 8H2.6958M2.6958 8L6.6958 12M2.6958 8L6.6958 4",
"stroke": "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
},
"name": "ArrowNarrowLeft"
}

View File

@@ -0,0 +1,14 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './ArrowNarrowLeft.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon

View File

@@ -1 +1,2 @@
export { default as ArrowNarrowLeft } from './ArrowNarrowLeft'
export { default as RefreshCw05 } from './RefreshCw05'

View File

@@ -0,0 +1,29 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "16",
"height": "16",
"viewBox": "0 0 16 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M13.6666 4.85185L7.99998 8M7.99998 8L2.33331 4.85185M7.99998 8L8 14.3333M14 10.7057V5.29431C14 5.06588 14 4.95167 13.9663 4.8498C13.9366 4.75969 13.8879 4.67696 13.8236 4.60717C13.7509 4.52828 13.651 4.47281 13.4514 4.36188L8.51802 1.62114C8.32895 1.5161 8.23442 1.46358 8.1343 1.44299C8.0457 1.42477 7.95431 1.42477 7.8657 1.44299C7.76559 1.46358 7.67105 1.5161 7.48198 1.62114L2.54865 4.36188C2.34896 4.47281 2.24912 4.52828 2.17642 4.60717C2.11211 4.67697 2.06343 4.75969 2.03366 4.84981C2 4.95167 2 5.06588 2 5.29431V10.7057C2 10.9341 2 11.0484 2.03366 11.1502C2.06343 11.2403 2.11211 11.3231 2.17642 11.3929C2.24912 11.4718 2.34897 11.5272 2.54865 11.6382L7.48198 14.3789C7.67105 14.4839 7.76559 14.5365 7.8657 14.557C7.95431 14.5753 8.0457 14.5753 8.1343 14.557C8.23442 14.5365 8.32895 14.4839 8.51802 14.3789L13.4514 11.6382C13.651 11.5272 13.7509 11.4718 13.8236 11.3929C13.8879 11.3231 13.9366 11.2403 13.9663 11.1502C14 11.0484 14 10.9341 14 10.7057Z",
"stroke": "currentColor",
"stroke-width": "1.25",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
},
"name": "Container"
}

View File

@@ -0,0 +1,14 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Container.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon

View File

@@ -0,0 +1,29 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "17",
"height": "16",
"viewBox": "0 0 17 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M14.5 3.33337C14.5 4.43794 11.8137 5.33337 8.5 5.33337C5.18629 5.33337 2.5 4.43794 2.5 3.33337M14.5 3.33337C14.5 2.2288 11.8137 1.33337 8.5 1.33337C5.18629 1.33337 2.5 2.2288 2.5 3.33337M14.5 3.33337V12.6667C14.5 13.7734 11.8333 14.6667 8.5 14.6667C5.16667 14.6667 2.5 13.7734 2.5 12.6667V3.33337M14.5 8.00004C14.5 9.10671 11.8333 10 8.5 10C5.16667 10 2.5 9.10671 2.5 8.00004",
"stroke": "currentColor",
"stroke-width": "1.25",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
},
"name": "Database01"
}

View File

@@ -0,0 +1,14 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Database01.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon

View File

@@ -0,0 +1,66 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "16",
"height": "16",
"viewBox": "0 0 16 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "puzzle-piece-01",
"clip-path": "url(#clip0_6770_9698)"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Icon",
"d": "M4.99992 3.00004C4.99992 2.07957 5.74611 1.33337 6.66659 1.33337C7.58706 1.33337 8.33325 2.07957 8.33325 3.00004V4.00004H8.99992C9.9318 4.00004 10.3977 4.00004 10.7653 4.15228C11.2553 4.35527 11.6447 4.74462 11.8477 5.23467C11.9999 5.60222 11.9999 6.06816 11.9999 7.00004H12.9999C13.9204 7.00004 14.6666 7.74623 14.6666 8.66671C14.6666 9.58718 13.9204 10.3334 12.9999 10.3334H11.9999V11.4667C11.9999 12.5868 11.9999 13.1469 11.7819 13.5747C11.5902 13.951 11.2842 14.257 10.9079 14.4487C10.4801 14.6667 9.92002 14.6667 8.79992 14.6667H8.33325V13.5C8.33325 12.6716 7.66168 12 6.83325 12C6.00483 12 5.33325 12.6716 5.33325 13.5V14.6667H4.53325C3.41315 14.6667 2.85309 14.6667 2.42527 14.4487C2.04895 14.257 1.74299 13.951 1.55124 13.5747C1.33325 13.1469 1.33325 12.5868 1.33325 11.4667V10.3334H2.33325C3.25373 10.3334 3.99992 9.58718 3.99992 8.66671C3.99992 7.74623 3.25373 7.00004 2.33325 7.00004H1.33325C1.33325 6.06816 1.33325 5.60222 1.48549 5.23467C1.68848 4.74462 2.07783 4.35527 2.56789 4.15228C2.93543 4.00004 3.40137 4.00004 4.33325 4.00004H4.99992V3.00004Z",
"stroke": "currentColor",
"stroke-width": "1.25",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
},
{
"type": "element",
"name": "defs",
"attributes": {},
"children": [
{
"type": "element",
"name": "clipPath",
"attributes": {
"id": "clip0_6770_9698"
},
"children": [
{
"type": "element",
"name": "rect",
"attributes": {
"width": "16",
"height": "16",
"fill": "white"
},
"children": []
}
]
}
]
}
]
},
"name": "PuzzlePiece01"
}

View File

@@ -0,0 +1,14 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './PuzzlePiece01.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon

View File

@@ -1 +1,4 @@
export { default as Container } from './Container'
export { default as Database01 } from './Database01'
export { default as Database03 } from './Database03'
export { default as PuzzlePiece01 } from './PuzzlePiece01'

View File

@@ -0,0 +1,83 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "17",
"height": "16",
"viewBox": "0 0 17 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "grid-01"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "Icon"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M6.1 2H3.56667C3.1933 2 3.00661 2 2.86401 2.07266C2.73856 2.13658 2.63658 2.23856 2.57266 2.36401C2.5 2.50661 2.5 2.6933 2.5 3.06667V5.6C2.5 5.97337 2.5 6.16005 2.57266 6.30266C2.63658 6.4281 2.73856 6.53009 2.86401 6.594C3.00661 6.66667 3.1933 6.66667 3.56667 6.66667H6.1C6.47337 6.66667 6.66005 6.66667 6.80266 6.594C6.9281 6.53009 7.03009 6.4281 7.094 6.30266C7.16667 6.16005 7.16667 5.97337 7.16667 5.6V3.06667C7.16667 2.6933 7.16667 2.50661 7.094 2.36401C7.03009 2.23856 6.9281 2.13658 6.80266 2.07266C6.66005 2 6.47337 2 6.1 2Z",
"stroke": "currentColor",
"stroke-width": "1.25",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M13.4333 2H10.9C10.5266 2 10.3399 2 10.1973 2.07266C10.0719 2.13658 9.96991 2.23856 9.906 2.36401C9.83333 2.50661 9.83333 2.6933 9.83333 3.06667V5.6C9.83333 5.97337 9.83333 6.16005 9.906 6.30266C9.96991 6.4281 10.0719 6.53009 10.1973 6.594C10.3399 6.66667 10.5266 6.66667 10.9 6.66667H13.4333C13.8067 6.66667 13.9934 6.66667 14.136 6.594C14.2614 6.53009 14.3634 6.4281 14.4273 6.30266C14.5 6.16005 14.5 5.97337 14.5 5.6V3.06667C14.5 2.6933 14.5 2.50661 14.4273 2.36401C14.3634 2.23856 14.2614 2.13658 14.136 2.07266C13.9934 2 13.8067 2 13.4333 2Z",
"stroke": "currentColor",
"stroke-width": "1.25",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M13.4333 9.33333H10.9C10.5266 9.33333 10.3399 9.33333 10.1973 9.406C10.0719 9.46991 9.96991 9.5719 9.906 9.69734C9.83333 9.83995 9.83333 10.0266 9.83333 10.4V12.9333C9.83333 13.3067 9.83333 13.4934 9.906 13.636C9.96991 13.7614 10.0719 13.8634 10.1973 13.9273C10.3399 14 10.5266 14 10.9 14H13.4333C13.8067 14 13.9934 14 14.136 13.9273C14.2614 13.8634 14.3634 13.7614 14.4273 13.636C14.5 13.4934 14.5 13.3067 14.5 12.9333V10.4C14.5 10.0266 14.5 9.83995 14.4273 9.69734C14.3634 9.5719 14.2614 9.46991 14.136 9.406C13.9934 9.33333 13.8067 9.33333 13.4333 9.33333Z",
"stroke": "currentColor",
"stroke-width": "1.25",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M6.1 9.33333H3.56667C3.1933 9.33333 3.00661 9.33333 2.86401 9.406C2.73856 9.46991 2.63658 9.5719 2.57266 9.69734C2.5 9.83995 2.5 10.0266 2.5 10.4V12.9333C2.5 13.3067 2.5 13.4934 2.57266 13.636C2.63658 13.7614 2.73856 13.8634 2.86401 13.9273C3.00661 14 3.1933 14 3.56667 14H6.1C6.47337 14 6.66005 14 6.80266 13.9273C6.9281 13.8634 7.03009 13.7614 7.094 13.636C7.16667 13.4934 7.16667 13.3067 7.16667 12.9333V10.4C7.16667 10.0266 7.16667 9.83995 7.094 9.69734C7.03009 9.5719 6.9281 9.46991 6.80266 9.406C6.66005 9.33333 6.47337 9.33333 6.1 9.33333Z",
"stroke": "currentColor",
"stroke-width": "1.25",
"stroke-linecap": "round",
"stroke-linejoin": "round"
},
"children": []
}
]
}
]
}
]
},
"name": "Grid01"
}

View File

@@ -0,0 +1,14 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Grid01.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon

View File

@@ -0,0 +1 @@
export { default as Grid01 } from './Grid01'

View File

@@ -0,0 +1,44 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "17",
"height": "16",
"viewBox": "0 0 17 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"d": "M8.29782 0.790031C8.12061 0.753584 7.93783 0.753584 7.76062 0.790031C7.55577 0.832161 7.37268 0.934712 7.22712 1.01624L7.18744 1.03841C6.01215 1.69134 4.02394 2.79644 2.90301 3.41952C2.63085 3.5708 2.49477 3.64644 2.44929 3.74641C2.40965 3.83357 2.4094 3.93356 2.4486 4.02091C2.49357 4.12111 2.62938 4.19751 2.90101 4.3503L7.76772 7.08785C7.8631 7.1415 7.91079 7.16832 7.96135 7.17884C8.0061 7.18814 8.05229 7.18814 8.09703 7.17884C8.1476 7.16832 8.19529 7.1415 8.29067 7.08785L13.1574 4.35029C13.429 4.1975 13.5649 4.12111 13.6098 4.02091C13.649 3.93355 13.6488 3.83356 13.6091 3.74641C13.5637 3.64644 13.4276 3.57079 13.1554 3.41951C12.0345 2.79644 10.0463 1.69134 8.871 1.03841L8.83132 1.01624C8.68576 0.934713 8.50267 0.832161 8.29782 0.790031Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M14.6932 5.92676C14.6929 5.62787 14.6928 5.47842 14.6297 5.39117C14.5748 5.31504 14.4902 5.26564 14.3969 5.25511C14.2899 5.24305 14.1594 5.31646 13.8984 5.46329L8.96774 8.23679C8.86877 8.29246 8.81928 8.3203 8.78326 8.35968C8.75139 8.39452 8.72729 8.43573 8.71254 8.48059C8.69588 8.53129 8.69588 8.58807 8.69588 8.70163V14.1518C8.69588 14.4499 8.69588 14.599 8.75856 14.6862C8.81326 14.7623 8.89744 14.8118 8.9905 14.8227C9.09716 14.8352 9.22706 14.763 9.48688 14.6188C10.5978 14.0019 12.6169 12.8807 13.8043 12.221L13.8464 12.1977C14.0005 12.1128 14.1943 12.0061 14.343 11.8447C14.4717 11.7051 14.569 11.5397 14.6286 11.3594C14.6975 11.1509 14.6966 10.9298 14.696 10.7538L14.6959 10.7058C14.6959 9.39704 14.6942 7.17087 14.6932 5.92676Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M6.57155 14.6187C6.83137 14.763 6.96128 14.8352 7.06793 14.8227C7.16099 14.8118 7.24518 14.7623 7.29987 14.6862C7.36255 14.599 7.36255 14.4499 7.36255 14.1518V8.70166C7.36255 8.5881 7.36255 8.53132 7.34589 8.48062C7.33114 8.43576 7.30704 8.39455 7.27517 8.35971C7.23915 8.32033 7.18966 8.29249 7.09069 8.23682L2.16004 5.4633C1.89902 5.31648 1.76851 5.24306 1.66154 5.25513C1.56823 5.26565 1.48367 5.31506 1.42869 5.39118C1.36566 5.47844 1.36553 5.62789 1.36528 5.92678C1.36424 7.17088 1.36255 9.39704 1.36255 10.7058L1.36243 10.7538C1.36179 10.9298 1.36099 11.1509 1.42986 11.3594C1.48941 11.5397 1.58676 11.7051 1.71539 11.8447C1.86417 12.0061 2.0579 12.1128 2.21199 12.1977L2.2541 12.221C3.44156 12.8807 5.46065 14.0019 6.57155 14.6187Z",
"fill": "currentColor"
},
"children": []
}
]
},
"name": "Container"
}

View File

@@ -0,0 +1,14 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Container.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon

View File

@@ -0,0 +1,46 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "17",
"height": "16",
"viewBox": "0 0 17 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"fill-rule": "evenodd",
"clip-rule": "evenodd",
"d": "M15.1956 4.66669V3.33335C15.1956 2.76539 14.8497 2.33041 14.4701 2.03126C14.083 1.72618 13.5641 1.48059 12.9824 1.28668C11.812 0.896551 10.2375 0.666687 8.52897 0.666687C6.8204 0.666687 5.24591 0.896551 4.07551 1.28668C3.4938 1.48059 2.97495 1.72618 2.58783 2.03126C2.20823 2.33041 1.8623 2.76539 1.8623 3.33335V4.66669C1.8623 5.23294 2.20443 5.66805 2.58368 5.96857C2.96958 6.27436 3.48705 6.52014 4.06786 6.71405C5.23637 7.10415 6.81113 7.33335 8.52897 7.33335C10.2468 7.33335 11.8216 7.10415 12.9901 6.71405C13.5709 6.52014 14.0884 6.27436 14.4743 5.96857C14.8535 5.66805 15.1956 5.23294 15.1956 4.66669ZM3.19564 3.33353C3.19564 3.33353 3.19576 3.33725 3.19767 3.34355C3.19994 3.35098 3.20552 3.36565 3.21902 3.38764C3.24732 3.43374 3.30502 3.50304 3.41313 3.58824C3.63325 3.76171 3.99308 3.94709 4.49715 4.11511C5.49832 4.44884 6.92383 4.66669 8.52897 4.66669C10.1341 4.66669 11.5596 4.44884 12.5608 4.11511C13.0649 3.94709 13.4247 3.76171 13.6448 3.58824C13.7529 3.50304 13.8106 3.43374 13.8389 3.38764C13.8524 3.36565 13.858 3.35098 13.8603 3.34355C13.8622 3.33716 13.8623 3.33335 13.8623 3.33335C13.8623 3.33335 13.8624 3.33006 13.8603 3.32316C13.858 3.31573 13.8524 3.30105 13.8389 3.27907C13.8106 3.23297 13.7529 3.16367 13.6448 3.07847C13.4247 2.905 13.0649 2.71962 12.5608 2.5516C11.5596 2.21787 10.1341 2.00002 8.52897 2.00002C6.92383 2.00002 5.49832 2.21787 4.49715 2.5516C3.99308 2.71962 3.63325 2.905 3.41313 3.07847C3.30502 3.16367 3.24732 3.23297 3.21902 3.27907C3.20552 3.30105 3.19994 3.31573 3.19767 3.32316C3.19563 3.32988 3.19564 3.33353 3.19564 3.33353Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M14.9234 7.00002C14.8447 7.00002 14.7705 7.03473 14.7155 7.09102C14.6407 7.16749 14.5613 7.23785 14.4802 7.30206C14.0939 7.60785 13.5759 7.85363 12.9945 8.04753C11.8249 8.43764 10.2485 8.66684 8.52896 8.66684C6.8094 8.66684 5.23307 8.43764 4.06339 8.04753C3.48201 7.85363 2.96401 7.60785 2.57773 7.30206C2.49661 7.23784 2.41719 7.16749 2.34244 7.09101C2.28743 7.03473 2.21322 7.00002 2.13452 7.00002C1.98418 7.00002 1.8623 7.12189 1.8623 7.27223V8.66669C1.8623 9.23294 2.20443 9.66805 2.58368 9.96857C2.96958 10.2744 3.48705 10.5201 4.06786 10.714C5.23637 11.1041 6.81113 11.3334 8.52897 11.3334C10.2468 11.3334 11.8216 11.1041 12.9901 10.714C13.5709 10.5201 14.0884 10.2744 14.4743 9.96857C14.8535 9.66805 15.1956 9.23294 15.1956 8.66669V7.27224C15.1956 7.1219 15.0738 7.00002 14.9234 7.00002Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"d": "M14.9234 11C14.8447 11 14.7705 11.0347 14.7155 11.091C14.6407 11.1675 14.5613 11.2378 14.4802 11.3021C14.0939 11.6079 13.5759 11.8536 12.9945 12.0475C11.8249 12.4376 10.2485 12.6668 8.52896 12.6668C6.8094 12.6668 5.23307 12.4376 4.06339 12.0475C3.48201 11.8536 2.96401 11.6079 2.57773 11.3021C2.49661 11.2378 2.41719 11.1675 2.34244 11.091C2.28743 11.0347 2.21322 11 2.13452 11C1.98418 11 1.8623 11.1219 1.8623 11.2722V12.6667C1.8623 13.2329 2.20443 13.668 2.58368 13.9686C2.96958 14.2744 3.48705 14.5201 4.06786 14.714C5.23637 15.1041 6.81113 15.3334 8.52897 15.3334C10.2468 15.3334 11.8216 15.1041 12.9901 14.714C13.5709 14.5201 14.0884 14.2744 14.4743 13.9686C14.8535 13.668 15.1956 13.2329 15.1956 12.6667V11.2722C15.1956 11.1219 15.0738 11 14.9234 11Z",
"fill": "currentColor"
},
"children": []
}
]
},
"name": "Database02"
}

View File

@@ -0,0 +1,14 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Database02.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon

View File

@@ -0,0 +1,38 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "17",
"height": "16",
"viewBox": "0 0 17 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "puzzle-piece-01"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"id": "Solid",
"fill-rule": "evenodd",
"clip-rule": "evenodd",
"d": "M4.83333 2.99999C4.83333 1.71133 5.878 0.666656 7.16667 0.666656C8.45533 0.666656 9.5 1.71133 9.5 2.99999V3.33332L9.52285 3.33332C9.96938 3.33332 10.338 3.33331 10.6397 3.3539C10.9525 3.37525 11.2419 3.42093 11.5205 3.53631C12.1739 3.80696 12.693 4.32609 12.9637 4.9795C13.0791 5.25804 13.1247 5.54744 13.1461 5.8603C13.1558 6.0027 13.1609 6.15998 13.1636 6.33332H13.5C14.7887 6.33332 15.8333 7.37799 15.8333 8.66666C15.8333 9.95532 14.7887 11 13.5 11H13.1667V11.4942C13.1667 12.0308 13.1667 12.4737 13.1372 12.8345C13.1066 13.2093 13.0409 13.5537 12.876 13.8773C12.6204 14.3791 12.2124 14.787 11.7106 15.0427C11.3871 15.2075 11.0426 15.2732 10.6679 15.3039C10.3071 15.3333 9.86419 15.3333 9.32755 15.3333H8.83333C8.46514 15.3333 8.16667 15.0348 8.16667 14.6667V13.5C8.16667 13.0398 7.79357 12.6667 7.33333 12.6667C6.8731 12.6667 6.5 13.0398 6.5 13.5V14.6667C6.5 15.0348 6.20152 15.3333 5.83333 15.3333H5.00578C4.46914 15.3333 4.02624 15.3333 3.66545 15.3039C3.29072 15.2732 2.94625 15.2075 2.62269 15.0427C2.12093 14.787 1.71298 14.3791 1.45732 13.8773C1.29246 13.5537 1.22675 13.2093 1.19613 12.8345C1.16665 12.4737 1.16666 12.0308 1.16667 11.4942L1.16667 10.3333C1.16667 9.96513 1.46514 9.66666 1.83333 9.66666H2.83333C3.38562 9.66666 3.83333 9.21894 3.83333 8.66666C3.83333 8.11437 3.38562 7.66666 2.83333 7.66666H1.83333C1.46514 7.66666 1.16667 7.36818 1.16667 6.99999L1.16667 6.97715C1.16666 6.53062 1.16666 6.16204 1.18724 5.8603C1.20859 5.54744 1.25428 5.25804 1.36965 4.9795C1.64031 4.32609 2.15944 3.80696 2.81284 3.53631C3.09139 3.42093 3.38078 3.37525 3.69364 3.3539C3.99538 3.33331 4.36396 3.33332 4.81048 3.33332L4.83333 3.33332L4.83333 2.99999Z",
"fill": "currentColor"
},
"children": []
}
]
}
]
},
"name": "PuzzlePiece01"
}

View File

@@ -0,0 +1,14 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './PuzzlePiece01.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon

View File

@@ -1 +1,4 @@
export { default as Container } from './Container'
export { default as Database02 } from './Database02'
export { default as Database03 } from './Database03'
export { default as PuzzlePiece01 } from './PuzzlePiece01'

View File

@@ -0,0 +1,79 @@
{
"icon": {
"type": "element",
"isRootNode": true,
"name": "svg",
"attributes": {
"width": "16",
"height": "16",
"viewBox": "0 0 16 16",
"fill": "none",
"xmlns": "http://www.w3.org/2000/svg"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "grid-01"
},
"children": [
{
"type": "element",
"name": "g",
"attributes": {
"id": "Solid"
},
"children": [
{
"type": "element",
"name": "path",
"attributes": {
"fill-rule": "evenodd",
"clip-rule": "evenodd",
"d": "M3.04545 1.33338C3.90407 1.33348 4.76437 1.33348 5.62131 1.33338C5.78956 1.33336 5.95343 1.33334 6.0922 1.34467C6.24459 1.35713 6.42442 1.3865 6.60536 1.4787C6.85625 1.60653 7.06022 1.81051 7.18805 2.06139C7.28025 2.24234 7.30963 2.42216 7.32208 2.57456C7.33342 2.71333 7.3334 2.8772 7.33338 3.04546V5.6213C7.3334 5.78956 7.33342 5.95342 7.32208 6.0922C7.30963 6.24459 7.28025 6.42442 7.18805 6.60536C7.06022 6.85625 6.85625 7.06022 6.60536 7.18805C6.42442 7.28025 6.24459 7.30963 6.0922 7.32208C5.95342 7.33342 5.78956 7.3334 5.6213 7.33338H3.04546C2.8772 7.3334 2.71333 7.33342 2.57456 7.32208C2.42216 7.30963 2.24234 7.28025 2.06139 7.18805C1.81051 7.06022 1.60653 6.85625 1.4787 6.60536C1.3865 6.42442 1.35713 6.24459 1.34467 6.0922C1.33334 5.95343 1.33336 5.78956 1.33338 5.62131C1.33338 5.61423 1.33338 5.60714 1.33338 5.60004V3.06671C1.33338 3.05962 1.33338 3.05253 1.33338 3.04545C1.33336 2.87719 1.33334 2.71333 1.34467 2.57456C1.35713 2.42216 1.3865 2.24234 1.4787 2.06139C1.60653 1.81051 1.81051 1.60653 2.06139 1.4787C2.24234 1.3865 2.42216 1.35713 2.57456 1.34467C2.71333 1.33334 2.87719 1.33336 3.04545 1.33338Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"fill-rule": "evenodd",
"clip-rule": "evenodd",
"d": "M3.04545 8.66671C3.90407 8.66682 4.76437 8.66682 5.62131 8.66671C5.78956 8.66669 5.95343 8.66667 6.0922 8.67801C6.24459 8.69046 6.42442 8.71984 6.60536 8.81204C6.85625 8.93987 7.06022 9.14384 7.18805 9.39472C7.28025 9.57567 7.30963 9.7555 7.32208 9.90789C7.33342 10.0467 7.3334 10.2105 7.33338 10.3788V12.9546C7.3334 13.1229 7.33342 13.2868 7.32208 13.4255C7.30963 13.5779 7.28025 13.7577 7.18805 13.9387C7.06022 14.1896 6.85625 14.3936 6.60536 14.5214C6.42442 14.6136 6.24459 14.643 6.0922 14.6554C5.95342 14.6668 5.78956 14.6667 5.6213 14.6667H3.04546C2.8772 14.6667 2.71333 14.6668 2.57456 14.6554C2.42216 14.643 2.24234 14.6136 2.06139 14.5214C1.81051 14.3936 1.60653 14.1896 1.4787 13.9387C1.3865 13.7577 1.35713 13.5779 1.34467 13.4255C1.33334 13.2868 1.33336 13.1229 1.33338 12.9546C1.33338 12.9476 1.33338 12.9405 1.33338 12.9334V10.4C1.33338 10.3929 1.33338 10.3859 1.33338 10.3788C1.33336 10.2105 1.33334 10.0467 1.34467 9.90789C1.35713 9.7555 1.3865 9.57567 1.4787 9.39472C1.60653 9.14384 1.81051 8.93987 2.06139 8.81204C2.24234 8.71984 2.42216 8.69046 2.57456 8.67801C2.71333 8.66667 2.87719 8.66669 3.04545 8.66671Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"fill-rule": "evenodd",
"clip-rule": "evenodd",
"d": "M10.3788 1.33338C11.2374 1.33348 12.0977 1.33348 12.9546 1.33338C13.1229 1.33336 13.2868 1.33334 13.4255 1.34467C13.5779 1.35713 13.7577 1.3865 13.9387 1.4787C14.1896 1.60653 14.3936 1.81051 14.5214 2.06139C14.6136 2.24234 14.643 2.42216 14.6554 2.57456C14.6668 2.71333 14.6667 2.8772 14.6667 3.04546V5.6213C14.6667 5.78956 14.6668 5.95342 14.6554 6.0922C14.643 6.24459 14.6136 6.42442 14.5214 6.60536C14.3936 6.85625 14.1896 7.06022 13.9387 7.18805C13.7577 7.28025 13.5779 7.30963 13.4255 7.32208C13.2868 7.33342 13.1229 7.3334 12.9546 7.33338H10.3788C10.2105 7.3334 10.0467 7.33342 9.90789 7.32208C9.7555 7.30963 9.57567 7.28025 9.39472 7.18805C9.14384 7.06022 8.93987 6.85625 8.81204 6.60536C8.71984 6.42442 8.69046 6.24459 8.67801 6.0922C8.66667 5.95343 8.66669 5.78956 8.66671 5.62131C8.66671 5.61423 8.66671 5.60714 8.66671 5.60004V3.06671C8.66671 3.05962 8.66671 3.05253 8.66671 3.04545C8.66669 2.87719 8.66667 2.71333 8.67801 2.57456C8.69046 2.42216 8.71984 2.24234 8.81204 2.06139C8.93987 1.81051 9.14384 1.60653 9.39472 1.4787C9.57567 1.3865 9.7555 1.35713 9.90789 1.34467C10.0467 1.33334 10.2105 1.33336 10.3788 1.33338Z",
"fill": "currentColor"
},
"children": []
},
{
"type": "element",
"name": "path",
"attributes": {
"fill-rule": "evenodd",
"clip-rule": "evenodd",
"d": "M10.3788 8.66671C11.2374 8.66682 12.0977 8.66682 12.9546 8.66671C13.1229 8.66669 13.2868 8.66667 13.4255 8.67801C13.5779 8.69046 13.7577 8.71984 13.9387 8.81204C14.1896 8.93987 14.3936 9.14384 14.5214 9.39472C14.6136 9.57567 14.643 9.7555 14.6554 9.90789C14.6668 10.0467 14.6667 10.2105 14.6667 10.3788V12.9546C14.6667 13.1229 14.6668 13.2868 14.6554 13.4255C14.643 13.5779 14.6136 13.7577 14.5214 13.9387C14.3936 14.1896 14.1896 14.3936 13.9387 14.5214C13.7577 14.6136 13.5779 14.643 13.4255 14.6554C13.2868 14.6668 13.1229 14.6667 12.9546 14.6667H10.3788C10.2105 14.6667 10.0467 14.6668 9.90789 14.6554C9.7555 14.643 9.57567 14.6136 9.39472 14.5214C9.14384 14.3936 8.93987 14.1896 8.81204 13.9387C8.71984 13.7577 8.69046 13.5779 8.67801 13.4255C8.66667 13.2868 8.66669 13.1229 8.66671 12.9546C8.66671 12.9476 8.66671 12.9405 8.66671 12.9334V10.4C8.66671 10.3929 8.66671 10.3859 8.66671 10.3788C8.66669 10.2105 8.66667 10.0467 8.67801 9.90789C8.69046 9.7555 8.71984 9.57567 8.81204 9.39472C8.93987 9.14384 9.14384 8.93987 9.39472 8.81204C9.57567 8.71984 9.7555 8.69046 9.90789 8.67801C10.0467 8.66667 10.2105 8.66669 10.3788 8.66671Z",
"fill": "currentColor"
},
"children": []
}
]
}
]
}
]
},
"name": "Grid01"
}

View File

@@ -0,0 +1,14 @@
// GENERATE BY script
// DON NOT EDIT IT MANUALLY
import * as React from 'react'
import data from './Grid01.json'
import IconBase from '@/app/components/base/icons/IconBase'
import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
props,
ref,
) => <IconBase {...props} ref={ref} data={data as IconData} />)
export default Icon

View File

@@ -0,0 +1 @@
export { default as Grid01 } from './Grid01'

View File

@@ -0,0 +1,58 @@
import { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useParams, usePathname } from 'next/navigation'
import useSWR from 'swr'
import useSWRInfinite from 'swr/infinite'
import { flatten } from 'lodash-es'
import Nav from '../nav'
import { fetchAppDetail, fetchAppList } from '@/service/apps'
import NewAppDialog from '@/app/(commonLayout)/apps/NewAppDialog'
import { Container } from '@/app/components/base/icons/src/vender/line/development'
import { Container as ContainerSolid } from '@/app/components/base/icons/src/vender/solid/development'
import type { AppListResponse } from '@/models/app'
const getKey = (pageIndex: number, previousPageData: AppListResponse) => {
if (!pageIndex || previousPageData.has_more)
return { url: 'apps', params: { page: pageIndex + 1, limit: 30 } }
return null
}
const AppNav = () => {
const { t } = useTranslation()
const [showNewAppDialog, setShowNewAppDialog] = useState(false)
const { appId } = useParams()
const isAppDetailPage = usePathname().split('/').includes('app')
const { data: currentApp } = useSWR((appId && isAppDetailPage) ? { url: '/apps', id: appId } : null, fetchAppDetail)
const { data: appsData, setSize } = useSWRInfinite(appId ? getKey : () => null, fetchAppList, { revalidateFirstPage: false })
const appItems = flatten(appsData?.map(appData => appData.data))
const handleLoadmore = useCallback(() => {
setSize(size => size + 1)
}, [setSize])
return (
<>
<Nav
icon={<Container className='w-4 h-4' />}
activeIcon={<ContainerSolid className='w-4 h-4' />}
text={t('common.menus.apps')}
activeSegment={['apps', 'app']}
link='/apps'
curNav={currentApp}
navs={appItems.map(item => ({
id: item.id,
name: item.name,
link: `/app/${item.id}/overview`,
icon: item.icon,
icon_background: item.icon_background,
}))}
createText={t('common.menus.newApp')}
onCreate={() => setShowNewAppDialog(true)}
onLoadmore={handleLoadmore}
/>
<NewAppDialog show={showNewAppDialog} onClose={() => setShowNewAppDialog(false)} />
</>
)
}
export default AppNav

View File

@@ -0,0 +1,53 @@
import { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useParams, useRouter } from 'next/navigation'
import useSWR from 'swr'
import useSWRInfinite from 'swr/infinite'
import { flatten } from 'lodash-es'
import Nav from '../nav'
import { fetchDataDetail, fetchDatasets } from '@/service/datasets'
import { Database01 } from '@/app/components/base/icons/src/vender/line/development'
import { Database02 } from '@/app/components/base/icons/src/vender/solid/development'
import type { DataSetListResponse } from '@/models/datasets'
const getKey = (pageIndex: number, previousPageData: DataSetListResponse) => {
if (!pageIndex || previousPageData.has_more)
return { url: 'datasets', params: { page: pageIndex + 1, limit: 30 } }
return null
}
const DatasetNav = () => {
const { t } = useTranslation()
const router = useRouter()
const { datasetId } = useParams()
const { data: currentDataset } = useSWR(datasetId || null, fetchDataDetail)
const { data: datasetsData, setSize } = useSWRInfinite(datasetId ? getKey : () => null, fetchDatasets, { revalidateFirstPage: true })
const datasetItems = flatten(datasetsData?.map(datasetData => datasetData.data))
const handleLoadmore = useCallback(() => {
setSize(size => size + 1)
}, [setSize])
return (
<Nav
icon={<Database01 className='w-4 h-4' />}
activeIcon={<Database02 className='w-4 h-4' />}
text={t('common.menus.datasets')}
activeSegment='datasets'
link='/datasets'
curNav={currentDataset}
navs={datasetItems.map(dataset => ({
id: dataset.id,
name: dataset.name,
link: `/datasets/${dataset.id}/documents`,
icon: dataset.icon,
icon_background: dataset.icon_background,
}))}
createText={t('common.menus.newDataset')}
onCreate={() => router.push('/datasets/create')}
onLoadmore={handleLoadmore}
/>
)
}
export default DatasetNav

View File

@@ -1,32 +1,23 @@
'use client'
import { useCallback, useEffect, useState } from 'react'
import { useEffect, useState } from 'react'
import type { FC } from 'react'
import useSWRInfinite from 'swr/infinite'
import { useTranslation } from 'react-i18next'
import { flatten } from 'lodash-es'
import { useRouter, useSelectedLayoutSegment } from 'next/navigation'
import { useSelectedLayoutSegment } from 'next/navigation'
import classNames from 'classnames'
import { CircleStackIcon, PuzzlePieceIcon } from '@heroicons/react/24/outline'
import { CommandLineIcon, Squares2X2Icon } from '@heroicons/react/24/solid'
import { CommandLineIcon } from '@heroicons/react/24/solid'
import Link from 'next/link'
import AccountDropdown from './account-dropdown'
import Nav from './nav'
import AppNav from './app-nav'
import DatasetNav from './dataset-nav'
import s from './index.module.css'
import type { GithubRepo, LangGeniusVersionResponse, UserProfileResponse } from '@/models/common'
import type { AppListResponse } from '@/models/app'
import NewAppDialog from '@/app/(commonLayout)/apps/NewAppDialog'
import { WorkspaceProvider } from '@/context/workspace-context'
import { useDatasetsContext } from '@/context/datasets-context'
import { fetchAppList } from '@/service/apps'
const BuildAppsIcon = ({ isSelected }: { isSelected: boolean }) => (
<svg className='mr-1' width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.6666 4.85221L7.99998 8.00036M7.99998 8.00036L2.33331 4.85221M7.99998 8.00036L8 14.3337M14 10.7061V5.29468C14 5.06625 14 4.95204 13.9663 4.85017C13.9366 4.76005 13.8879 4.67733 13.8236 4.60754C13.7509 4.52865 13.651 4.47318 13.4514 4.36224L8.51802 1.6215C8.32895 1.51646 8.23442 1.46395 8.1343 1.44336C8.0457 1.42513 7.95431 1.42513 7.8657 1.44336C7.76559 1.46395 7.67105 1.51646 7.48198 1.6215L2.54865 4.36225C2.34896 4.47318 2.24912 4.52865 2.17642 4.60754C2.11211 4.67733 2.06343 4.76005 2.03366 4.85017C2 4.95204 2 5.06625 2 5.29468V10.7061C2 10.9345 2 11.0487 2.03366 11.1506C2.06343 11.2407 2.11211 11.3234 2.17642 11.3932C2.24912 11.4721 2.34897 11.5276 2.54865 11.6385L7.48198 14.3793C7.67105 14.4843 7.76559 14.5368 7.8657 14.5574C7.95431 14.5756 8.0457 14.5756 8.1343 14.5574C8.23442 14.5368 8.32895 14.4843 8.51802 14.3793L13.4514 11.6385C13.651 11.5276 13.7509 11.4721 13.8236 11.3932C13.8879 11.3234 13.9366 11.2407 13.9663 11.1506C14 11.0487 14 10.9345 14 10.7061Z" stroke={isSelected ? '#155EEF' : '#667085'} strokeWidth="1.25" strokeLinecap="round" strokeLinejoin="round"/>
</svg>
)
import { Grid01 } from '@/app/components/base/icons/src/vender/line/layout'
import { Grid01 as Grid01Solid } from '@/app/components/base/icons/src/vender/solid/layout'
import { PuzzlePiece01 } from '@/app/components/base/icons/src/vender/line/development'
import { PuzzlePiece01 as PuzzlePiece01Solid } from '@/app/components/base/icons/src/vender/solid/development'
export type IHeaderProps = {
curAppId?: string
userProfile: UserProfileResponse
onLogout: () => void
langeniusVersionInfo: LangGeniusVersionResponse
@@ -34,30 +25,20 @@ export type IHeaderProps = {
}
const navClassName = `
flex items-center relative mr-3 px-3 h-8 rounded-xl
font-medium text-[14px]
font-medium text-sm
cursor-pointer
`
const headerEnvClassName: { [k: string]: string } = {
DEVELOPMENT: 'bg-[#FEC84B] border-[#FDB022] text-[#93370D]',
TESTING: 'bg-[#A5F0FC] border-[#67E3F9] text-[#164C63]',
}
const getKey = (pageIndex: number, previousPageData: AppListResponse) => {
if (!pageIndex || previousPageData.has_more)
return { url: 'apps', params: { page: pageIndex + 1, limit: 30 } }
return null
}
const Header: FC<IHeaderProps> = ({
curAppId,
userProfile,
onLogout,
langeniusVersionInfo,
isBordered,
}) => {
const { t } = useTranslation()
const [showNewAppDialog, setShowNewAppDialog] = useState(false)
const { data: appsData, isLoading, setSize } = useSWRInfinite(curAppId ? getKey : () => null, fetchAppList, { revalidateFirstPage: false })
const { datasets, currentDataset } = useDatasetsContext()
const router = useRouter()
const showEnvTag = langeniusVersionInfo.current_env === 'TESTING' || langeniusVersionInfo.current_env === 'DEVELOPMENT'
const selectedSegment = useSelectedLayoutSegment()
const isPluginsComingSoon = selectedSegment === 'plugins-coming-soon'
@@ -69,14 +50,6 @@ const Header: FC<IHeaderProps> = ({
setStarCount(data.stargazers_count)
})
}, [])
const appItems = flatten(appsData?.map(appData => appData.data))
const handleLoadmore = useCallback(() => {
if (isLoading)
return
setSize(size => size + 1)
}, [setSize, isLoading])
return (
<div className={classNames(
@@ -112,52 +85,29 @@ const Header: FC<IHeaderProps> = ({
<Link href="/explore/apps" className={classNames(
navClassName, 'group',
isExplore && 'bg-white shadow-[0_2px_5px_-1px_rgba(0,0,0,0.05),0_2px_4px_-2px_rgba(0,0,0,0.05)]',
isExplore ? 'text-primary-600' : 'text-gray-500 hover:bg-gray-200 hover:text-gray-700',
isExplore ? 'text-primary-600' : 'text-gray-500 hover:bg-gray-200',
)}>
<Squares2X2Icon className='mr-1 w-[18px] h-[18px]' />
{
isExplore
? <Grid01Solid className='mr-2 w-4 h-4' />
: <Grid01 className='mr-2 w-4 h-4' />
}
{t('common.menus.explore')}
</Link>
<Nav
icon={<BuildAppsIcon isSelected={['apps', 'app'].includes(selectedSegment || '')} />}
text={t('common.menus.apps')}
activeSegment={['apps', 'app']}
link='/apps'
curNav={appItems.find(appItem => appItem.id === curAppId)}
navs={appItems.map(item => ({
id: item.id,
name: item.name,
link: `/app/${item.id}/overview`,
icon: item.icon,
icon_background: item.icon_background,
}))}
createText={t('common.menus.newApp')}
onCreate={() => setShowNewAppDialog(true)}
onLoadmore={handleLoadmore}
/>
<AppNav />
<Link href="/plugins-coming-soon" className={classNames(
navClassName, 'group',
isPluginsComingSoon && 'bg-white shadow-[0_2px_5px_-1px_rgba(0,0,0,0.05),0_2px_4px_-2px_rgba(0,0,0,0.05)]',
isPluginsComingSoon ? 'text-primary-600' : 'text-gray-500 hover:bg-gray-200 hover:text-gray-700',
isPluginsComingSoon ? 'text-primary-600' : 'text-gray-500 hover:bg-gray-200',
)}>
<PuzzlePieceIcon className='mr-1 w-[18px] h-[18px]' />
{
isPluginsComingSoon
? <PuzzlePiece01Solid className='mr-2 w-4 h-4' />
: <PuzzlePiece01 className='mr-2 w-4 h-4' />
}
{t('common.menus.plugins')}
</Link>
<Nav
icon={<CircleStackIcon className='mr-1 w-[18px] h-[18px]' />}
text={t('common.menus.datasets')}
activeSegment='datasets'
link='/datasets'
curNav={currentDataset && { id: currentDataset.id, name: currentDataset.name, icon: currentDataset.icon, icon_background: currentDataset.icon_background }}
navs={datasets.map(dataset => ({
id: dataset.id,
name: dataset.name,
link: `/datasets/${dataset.id}/documents`,
icon: dataset.icon,
icon_background: dataset.icon_background,
}))}
createText={t('common.menus.newDataset')}
onCreate={() => router.push('/datasets/create')}
/>
<DatasetNav />
</div>
<div className='flex items-center flex-shrink-0'>
{
@@ -190,7 +140,6 @@ const Header: FC<IHeaderProps> = ({
</WorkspaceProvider>
</div>
</div>
<NewAppDialog show={showNewAppDialog} onClose={() => setShowNewAppDialog(false)} />
</div>
)
}

View File

@@ -4,12 +4,13 @@ import React, { useState } from 'react'
import Link from 'next/link'
import { useSelectedLayoutSegment } from 'next/navigation'
import classNames from 'classnames'
import { ArrowLeftIcon } from '@heroicons/react/24/solid'
import type { INavSelectorProps } from './nav-selector'
import NavSelector from './nav-selector'
import { ArrowNarrowLeft } from '@/app/components/base/icons/src/vender/line/arrows'
type INavProps = {
icon: React.ReactNode
activeIcon?: React.ReactNode
text: string
activeSegment: string | string[]
link: string
@@ -17,6 +18,7 @@ type INavProps = {
const Nav = ({
icon,
activeIcon,
text,
activeSegment,
link,
@@ -32,25 +34,29 @@ const Nav = ({
return (
<div className={`
flex items-center h-8 mr-3 px-0.5 rounded-xl text-[14px] shrink-0
${isActived && 'bg-white shadow-[0_2px_5px_-1px_rgba(0,0,0,0.05),0_2px_4px_-2px_rgba(0,0,0,0.05)]'}
flex items-center h-8 mr-3 px-0.5 rounded-xl text-sm shrink-0 font-medium
${isActived && 'bg-white shadow-[0_2px_5px_-1px_rgba(0,0,0,0.05),0_2px_4px_-2px_rgba(0,0,0,0.05)] font-semibold'}
${!curNav && !isActived && 'hover:bg-gray-200'}
`}>
<Link href={link}>
<div
className={classNames(`
flex items-center h-7 pl-2.5 pr-2
font-semibold cursor-pointer rounded-[10px]
${isActived ? 'text-[#1C64F2]' : 'text-gray-500 hover:bg-gray-200'}
${curNav && isActived && 'hover:bg-[#EBF5FF]'}
flex items-center h-7 px-2.5 cursor-pointer rounded-[10px]
${isActived ? 'text-primary-600' : 'text-gray-500'}
${curNav && isActived && 'hover:bg-primary-50'}
`)}
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
>
{
(hovered && curNav && isActived)
? <ArrowLeftIcon className='mr-1 w-[18px] h-[18px]' />
: icon
}
<div className='mr-2'>
{
(hovered && curNav)
? <ArrowNarrowLeft className='w-4 h-4' />
: isActived
? activeIcon
: icon
}
</div>
{text}
</div>
</Link>

View File

@@ -1,12 +1,13 @@
import { useState } from 'react'
import type { ConversationItem } from '@/models/share'
import produce from 'immer'
import type { ConversationItem } from '@/models/share'
const storageConversationIdKey = 'conversationIdInfo'
type ConversationInfoType = Omit<ConversationItem, 'inputs' | 'id'>
function useConversation() {
const [conversationList, setConversationList] = useState<ConversationItem[]>([])
const [pinnedConversationList, setPinnedConversationList] = useState<ConversationItem[]>([])
const [currConversationId, doSetCurrConversationId] = useState<string>('-1')
// when set conversation id, we do not have set appId
const setCurrConversationId = (id: string, appId: string, isSetToLocalStroge = true, newConversationName = '') => {
@@ -29,9 +30,10 @@ function useConversation() {
// input can be updated by user
const [newConversationInputs, setNewConversationInputs] = useState<Record<string, any> | null>(null)
const resetNewConversationInputs = () => {
if (!newConversationInputs) return
setNewConversationInputs(produce(newConversationInputs, draft => {
Object.keys(draft).forEach(key => {
if (!newConversationInputs)
return
setNewConversationInputs(produce(newConversationInputs, (draft) => {
Object.keys(draft).forEach((key) => {
draft[key] = ''
})
}))
@@ -48,6 +50,8 @@ function useConversation() {
return {
conversationList,
setConversationList,
pinnedConversationList,
setPinnedConversationList,
currConversationId,
setCurrConversationId,
getConversationIdFromStorage,
@@ -59,8 +63,8 @@ function useConversation() {
setCurrInputs,
currConversationInfo,
setNewConversationInfo,
setExistConversationInfo
setExistConversationInfo,
}
}
export default useConversation;
export default useConversation

View File

@@ -14,7 +14,7 @@ import { ToastContext } from '@/app/components/base/toast'
import Sidebar from '@/app/components/share/chat/sidebar'
import ConfigSence from '@/app/components/share/chat/config-scence'
import Header from '@/app/components/share/header'
import { fetchAppInfo, fetchAppParams, fetchChatList, fetchConversations, fetchSuggestedQuestions, sendChatMessage, stopChatMessageResponding, updateFeedback } from '@/service/share'
import { fetchAppInfo, fetchAppParams, fetchChatList, fetchConversations, fetchSuggestedQuestions, pinConversation, sendChatMessage, stopChatMessageResponding, unpinConversation, updateFeedback } from '@/service/share'
import type { ConversationItem, SiteInfo } from '@/models/share'
import type { PromptConfig, SuggestedQuestionsAfterAnswerConfig } from '@/models/debug'
import type { Feedbacktype, IChatItem } from '@/app/components/app/chat'
@@ -65,9 +65,12 @@ const Main: FC<IMainProps> = ({
/*
* conversation info
*/
const [allConversationList, setAllConversationList] = useState<ConversationItem[]>([])
const {
conversationList,
setConversationList,
pinnedConversationList,
setPinnedConversationList,
currConversationId,
setCurrConversationId,
getConversationIdFromStorage,
@@ -81,11 +84,36 @@ const Main: FC<IMainProps> = ({
setNewConversationInfo,
setExistConversationInfo,
} = useConversation()
const [hasMore, setHasMore] = useState<boolean>(false)
const [hasMore, setHasMore] = useState<boolean>(true)
const [hasPinnedMore, setHasPinnedMore] = useState<boolean>(true)
const onMoreLoaded = ({ data: conversations, has_more }: any) => {
setHasMore(has_more)
setConversationList([...conversationList, ...conversations])
}
const onPinnedMoreLoaded = ({ data: conversations, has_more }: any) => {
setHasPinnedMore(has_more)
setPinnedConversationList([...pinnedConversationList, ...conversations])
}
const [controlUpdateConversationList, setControlUpdateConversationList] = useState(0)
const noticeUpdateList = () => {
setConversationList([])
setHasMore(true)
setPinnedConversationList([])
setHasPinnedMore(true)
setControlUpdateConversationList(Date.now())
}
const handlePin = async (id: string) => {
await pinConversation(isInstalledApp, installedAppInfo?.id, id)
notify({ type: 'success', message: t('common.api.success') })
noticeUpdateList()
}
const handleUnpin = async (id: string) => {
await unpinConversation(isInstalledApp, installedAppInfo?.id, id)
notify({ type: 'success', message: t('common.api.success') })
noticeUpdateList()
}
const [suggestedQuestionsAfterAnswerConfig, setSuggestedQuestionsAfterAnswerConfig] = useState<SuggestedQuestionsAfterAnswerConfig | null>(null)
const [conversationIdChangeBecauseOfNew, setConversationIdChangeBecauseOfNew, getConversationIdChangeBecauseOfNew] = useGetState(false)
@@ -121,7 +149,7 @@ const Main: FC<IMainProps> = ({
let notSyncToStateIntroduction = ''
let notSyncToStateInputs: Record<string, any> | undefined | null = {}
if (!isNewConversation) {
const item = conversationList.find(item => item.id === currConversationId)
const item = allConversationList.find(item => item.id === currConversationId)
notSyncToStateInputs = item?.inputs || {}
setCurrInputs(notSyncToStateInputs)
notSyncToStateIntroduction = item?.introduction || ''
@@ -229,6 +257,10 @@ const Main: FC<IMainProps> = ({
return []
}
const fetchAllConversations = () => {
return fetchConversations(isInstalledApp, installedAppInfo?.id, undefined, undefined, 100)
}
const fetchInitData = () => {
return Promise.all([isInstalledApp
? {
@@ -240,7 +272,7 @@ const Main: FC<IMainProps> = ({
},
plan: 'basic',
}
: fetchAppInfo(), fetchConversations(isInstalledApp, installedAppInfo?.id), fetchAppParams(isInstalledApp, installedAppInfo?.id)])
: fetchAppInfo(), fetchAllConversations(), fetchAppParams(isInstalledApp, installedAppInfo?.id)])
}
// init
@@ -255,10 +287,10 @@ const Main: FC<IMainProps> = ({
setIsPublicVersion(tempIsPublicVersion)
const prompt_template = ''
// handle current conversation id
const { data: conversations, has_more } = conversationData as { data: ConversationItem[]; has_more: boolean }
const { data: allConversations } = conversationData as { data: ConversationItem[]; has_more: boolean }
const _conversationId = getConversationIdFromStorage(appId)
const isNotNewConversation = conversations.some(item => item.id === _conversationId)
setHasMore(has_more)
const isNotNewConversation = allConversations.some(item => item.id === _conversationId)
setAllConversationList(allConversations)
// fetch new conversation info
const { user_input_form, opening_statement: introduction, suggested_questions_after_answer }: any = appParams
const prompt_variables = userInputsFormToPromptVariables(user_input_form)
@@ -276,7 +308,7 @@ const Main: FC<IMainProps> = ({
} as PromptConfig)
setSuggestedQuestionsAfterAnswerConfig(suggested_questions_after_answer)
setConversationList(conversations as ConversationItem[])
// setConversationList(conversations as ConversationItem[])
if (isNotNewConversation)
setCurrConversationId(_conversationId, appId, false)
@@ -403,12 +435,10 @@ const Main: FC<IMainProps> = ({
if (hasError)
return
let currChatList = conversationList
if (getConversationIdChangeBecauseOfNew()) {
const { data: conversations, has_more }: any = await fetchConversations(isInstalledApp, installedAppInfo?.id)
setHasMore(has_more)
setConversationList(conversations as ConversationItem[])
currChatList = conversations
const { data: allConversations }: any = await fetchAllConversations()
setAllConversationList(allConversations)
noticeUpdateList()
}
setConversationIdChangeBecauseOfNew(false)
resetNewConversationInputs()
@@ -451,14 +481,20 @@ const Main: FC<IMainProps> = ({
return (
<Sidebar
list={conversationList}
pinnedList={pinnedConversationList}
onMoreLoaded={onMoreLoaded}
onPinnedMoreLoaded={onPinnedMoreLoaded}
isNoMore={!hasMore}
isPinnedNoMore={!hasPinnedMore}
onCurrentIdChange={handleConversationIdChange}
currentId={currConversationId}
copyRight={siteInfo.copyright || siteInfo.title}
isInstalledApp={isInstalledApp}
installedAppId={installedAppInfo?.id}
siteInfo={siteInfo}
onPin={handlePin}
onUnpin={handleUnpin}
controlUpdateList={controlUpdateConversationList}
/>
)
}
@@ -482,9 +518,6 @@ const Main: FC<IMainProps> = ({
/>
)}
{/* {isNewConversation ? 'new' : 'exist'}
{JSON.stringify(newConversationInputs ? newConversationInputs : {})}
{JSON.stringify(existConversationInputs ? existConversationInputs : {})} */}
<div
className={cn(
'flex rounded-t-2xl bg-white overflow-hidden',

View File

@@ -1,32 +1,33 @@
import React, { useRef } from 'react'
import React, { useEffect, useState } from 'react'
import type { FC } from 'react'
import { useTranslation } from 'react-i18next'
import {
ChatBubbleOvalLeftEllipsisIcon,
PencilSquareIcon,
} from '@heroicons/react/24/outline'
import { ChatBubbleOvalLeftEllipsisIcon as ChatBubbleOvalLeftEllipsisSolidIcon } from '@heroicons/react/24/solid'
import { useInfiniteScroll } from 'ahooks'
import cn from 'classnames'
import Button from '../../../base/button'
import List from './list'
import AppInfo from '@/app/components/share/chat/sidebar/app-info'
// import Card from './card'
import type { ConversationItem, SiteInfo } from '@/models/share'
import { fetchConversations } from '@/service/share'
function classNames(...classes: any[]) {
return classes.filter(Boolean).join(' ')
}
export type ISidebarProps = {
copyRight: string
currentId: string
onCurrentIdChange: (id: string) => void
list: ConversationItem[]
pinnedList: ConversationItem[]
isInstalledApp: boolean
installedAppId?: string
siteInfo: SiteInfo
onMoreLoaded: (res: { data: ConversationItem[]; has_more: boolean }) => void
onPinnedMoreLoaded: (res: { data: ConversationItem[]; has_more: boolean }) => void
isNoMore: boolean
isPinnedNoMore: boolean
onPin: (id: string) => void
onUnpin: (id: string) => void
controlUpdateList: number
}
const Sidebar: FC<ISidebarProps> = ({
@@ -34,37 +35,41 @@ const Sidebar: FC<ISidebarProps> = ({
currentId,
onCurrentIdChange,
list,
pinnedList,
isInstalledApp,
installedAppId,
siteInfo,
onMoreLoaded,
onPinnedMoreLoaded,
isNoMore,
isPinnedNoMore,
onPin,
onUnpin,
controlUpdateList,
}) => {
const { t } = useTranslation()
const listRef = useRef<HTMLDivElement>(null)
const [hasPinned, setHasPinned] = useState(false)
useInfiniteScroll(
async () => {
if (!isNoMore) {
const lastId = list[list.length - 1].id
const { data: conversations, has_more }: any = await fetchConversations(isInstalledApp, installedAppId, lastId)
onMoreLoaded({ data: conversations, has_more })
}
return { list: [] }
},
{
target: listRef,
isNoMore: () => {
return isNoMore
},
reloadDeps: [isNoMore],
},
)
const checkHasPinned = async () => {
const { data }: any = await fetchConversations(isInstalledApp, installedAppId, undefined, true)
setHasPinned(data.length > 0)
}
useEffect(() => {
checkHasPinned()
}, [])
useEffect(() => {
if (controlUpdateList !== 0)
checkHasPinned()
}, [controlUpdateList])
const maxListHeight = isInstalledApp ? 'max-h-[30vh]' : 'max-h-[40vh]'
return (
<div
className={
classNames(
cn(
isInstalledApp ? 'tablet:h-[calc(100vh_-_74px)]' : 'tablet:h-[calc(100vh_-_3rem)]',
'shrink-0 flex flex-col bg-white pc:w-[244px] tablet:w-[192px] mobile:w-[240px] border-r border-gray-200 mobile:h-screen',
)
@@ -85,40 +90,46 @@ const Sidebar: FC<ISidebarProps> = ({
<PencilSquareIcon className="mr-2 h-4 w-4" /> {t('share.chat.newChat')}
</Button>
</div>
<nav
ref={listRef}
className="mt-4 flex-1 space-y-1 bg-white p-4 !pt-0 overflow-y-auto"
>
{list.map((item) => {
const isCurrent = item.id === currentId
const ItemIcon
= isCurrent ? ChatBubbleOvalLeftEllipsisSolidIcon : ChatBubbleOvalLeftEllipsisIcon
return (
<div
onClick={() => onCurrentIdChange(item.id)}
key={item.id}
className={classNames(
isCurrent
? 'bg-primary-50 text-primary-600'
: 'text-gray-700 hover:bg-gray-100 hover:text-gray-700',
'group flex items-center rounded-md px-2 py-2 text-sm font-medium cursor-pointer',
)}
>
<ItemIcon
className={classNames(
isCurrent
? 'text-primary-600'
: 'text-gray-400 group-hover:text-gray-500',
'mr-3 h-5 w-5 flex-shrink-0',
)}
aria-hidden="true"
/>
{item.name}
</div>
)
})}
</nav>
<div className='flex-grow h-0 overflow-y-auto overflow-x-hidden'>
{/* pinned list */}
{hasPinned && (
<div className='mt-4 px-4'>
<div className='mb-1.5 leading-[18px] text-xs text-gray-500 font-medium uppercase'>{t('share.chat.pinnedTitle')}</div>
<List
className={maxListHeight}
currentId={currentId}
onCurrentIdChange={onCurrentIdChange}
list={pinnedList}
isInstalledApp={isInstalledApp}
installedAppId={installedAppId}
onMoreLoaded={onPinnedMoreLoaded}
isNoMore={isPinnedNoMore}
isPinned={true}
onPinChanged={id => onUnpin(id)}
controlUpdate={controlUpdateList + 1}
/>
</div>
)}
{/* unpinned list */}
<div className='mt-4 px-4'>
{hasPinned && (
<div className='mb-1.5 leading-[18px] text-xs text-gray-500 font-medium uppercase'>{t('share.chat.unpinnedTitle')}</div>
)}
<List
className={cn(hasPinned ? maxListHeight : 'flex-grow')}
currentId={currentId}
onCurrentIdChange={onCurrentIdChange}
list={list}
isInstalledApp={isInstalledApp}
installedAppId={installedAppId}
onMoreLoaded={onMoreLoaded}
isNoMore={isNoMore}
isPinned={false}
onPinChanged={id => onPin(id)}
controlUpdate={controlUpdateList + 1}
/>
</div>
</div>
<div className="flex flex-shrink-0 pr-4 pb-4 pl-4">
<div className="text-gray-400 font-normal text-xs">© {copyRight} {(new Date()).getFullYear()}</div>
</div>

View File

@@ -0,0 +1,113 @@
'use client'
import type { FC } from 'react'
import React, { useRef } from 'react'
import {
ChatBubbleOvalLeftEllipsisIcon,
} from '@heroicons/react/24/outline'
import { useInfiniteScroll } from 'ahooks'
import { ChatBubbleOvalLeftEllipsisIcon as ChatBubbleOvalLeftEllipsisSolidIcon } from '@heroicons/react/24/solid'
import cn from 'classnames'
import s from './style.module.css'
import type { ConversationItem } from '@/models/share'
import { fetchConversations } from '@/service/share'
import ItemOperation from '@/app/components/explore/item-operation'
export type IListProps = {
className: string
currentId: string
onCurrentIdChange: (id: string) => void
list: ConversationItem[]
isInstalledApp: boolean
installedAppId?: string
onMoreLoaded: (res: { data: ConversationItem[]; has_more: boolean }) => void
isNoMore: boolean
isPinned: boolean
onPinChanged: (id: string) => void
controlUpdate: number
}
const List: FC<IListProps> = ({
className,
currentId,
onCurrentIdChange,
list,
isInstalledApp,
installedAppId,
onMoreLoaded,
isNoMore,
isPinned,
onPinChanged,
controlUpdate,
}) => {
const listRef = useRef<HTMLDivElement>(null)
useInfiniteScroll(
async () => {
if (!isNoMore) {
const lastId = list[list.length - 1]?.id
const { data: conversations, has_more }: any = await fetchConversations(isInstalledApp, installedAppId, lastId, isPinned)
onMoreLoaded({ data: conversations, has_more })
}
return { list: [] }
},
{
target: listRef,
isNoMore: () => {
return isNoMore
},
reloadDeps: [isNoMore, controlUpdate],
},
)
return (
<nav
ref={listRef}
className={cn(className, 'shrink-0 space-y-1 bg-white pb-[60px] overflow-y-auto')}
>
{list.map((item) => {
const isCurrent = item.id === currentId
const ItemIcon
= isCurrent ? ChatBubbleOvalLeftEllipsisSolidIcon : ChatBubbleOvalLeftEllipsisIcon
return (
<div
onClick={() => onCurrentIdChange(item.id)}
key={item.id}
className={cn(s.item,
isCurrent
? 'bg-primary-50 text-primary-600'
: 'text-gray-700 hover:bg-gray-200 hover:text-gray-700',
'group flex justify-between items-center rounded-md px-2 py-2 text-sm font-medium cursor-pointer',
)}
>
<div className='flex items-center w-0 grow'>
<ItemIcon
className={cn(
isCurrent
? 'text-primary-600'
: 'text-gray-400 group-hover:text-gray-500',
'mr-3 h-5 w-5 flex-shrink-0',
)}
aria-hidden="true"
/>
<span>{item.name}</span>
</div>
{
!isCurrent && (
<div className={cn(s.opBtn, 'shrink-0')} onClick={e => e.stopPropagation()}>
<ItemOperation
isPinned={isPinned}
togglePin={() => onPinChanged(item.id)}
isShowDelete={false}
onDelete={() => {}}
/>
</div>
)
}
</div>
)
})}
</nav>
)
}
export default React.memo(List)

View File

@@ -0,0 +1,7 @@
.opBtn {
visibility: hidden;
}
.item:hover .opBtn {
visibility: visible;
}

View File

@@ -1,45 +1,47 @@
const translation = {
common: {
welcome: "Welcome to use",
appUnavailable: "App is unavailable",
appUnkonwError: "App is unavailable"
welcome: 'Welcome to use',
appUnavailable: 'App is unavailable',
appUnkonwError: 'App is unavailable',
},
chat: {
newChat: "New chat",
newChatDefaultName: "New conversation",
powerBy: "Powered by",
prompt: "Prompt",
privatePromptConfigTitle: "Conversation settings",
publicPromptConfigTitle: "Initial Prompt",
configStatusDes: "Before start, you can modify conversation settings",
newChat: 'New chat',
pinnedTitle: 'Pinned',
unpinnedTitle: 'Chats',
newChatDefaultName: 'New conversation',
powerBy: 'Powered by',
prompt: 'Prompt',
privatePromptConfigTitle: 'Conversation settings',
publicPromptConfigTitle: 'Initial Prompt',
configStatusDes: 'Before start, you can modify conversation settings',
configDisabled:
"Previous session settings have been used for this session.",
startChat: "Start Chat",
'Previous session settings have been used for this session.',
startChat: 'Start Chat',
privacyPolicyLeft:
"Please read the ",
'Please read the ',
privacyPolicyMiddle:
"privacy policy",
'privacy policy',
privacyPolicyRight:
" provided by the app developer.",
' provided by the app developer.',
},
generation: {
tabs: {
create: "Create",
saved: "Saved",
create: 'Create',
saved: 'Saved',
},
savedNoData: {
title: "You haven't saved a result yet!",
title: 'You haven\'t saved a result yet!',
description: 'Start generating content, and find your saved results here.',
startCreateContent: 'Start create content'
startCreateContent: 'Start create content',
},
title: "AI Completion",
queryTitle: "Query content",
queryPlaceholder: "Write your query content...",
run: "RUN",
copy: "Copy",
resultTitle: "AI Completion",
noData: "AI will give you what you want here.",
title: 'AI Completion',
queryTitle: 'Query content',
queryPlaceholder: 'Write your query content...',
run: 'RUN',
copy: 'Copy',
resultTitle: 'AI Completion',
noData: 'AI will give you what you want here.',
},
};
}
export default translation;
export default translation

View File

@@ -1,41 +1,43 @@
const translation = {
common: {
welcome: "欢迎使用",
appUnavailable: "应用不可用",
appUnkonwError: "应用不可用",
welcome: '欢迎使用',
appUnavailable: '应用不可用',
appUnkonwError: '应用不可用',
},
chat: {
newChat: "新对话",
newChatDefaultName: "新的对话",
powerBy: "Powered by",
prompt: "提示词",
privatePromptConfigTitle: "对话设置",
publicPromptConfigTitle: "对话前提示词",
configStatusDes: "开始前,您可以修改对话设置",
configDisabled: "此次会话已使用上次会话表单",
startChat: "开始对话",
privacyPolicyLeft: "请阅读由该应用开发者提供的",
privacyPolicyMiddle: "隐私政策",
privacyPolicyRight: "。",
newChat: '新对话',
pinnedTitle: '已置顶',
unpinnedTitle: '对话列表',
newChatDefaultName: '新的对话',
powerBy: 'Powered by',
prompt: '提示词',
privatePromptConfigTitle: '对话设置',
publicPromptConfigTitle: '对话前提示词',
configStatusDes: '开始前,您可以修改对话设置',
configDisabled: '此次会话已使用上次会话表单',
startChat: '开始对话',
privacyPolicyLeft: '请阅读由该应用开发者提供的',
privacyPolicyMiddle: '隐私政策',
privacyPolicyRight: '。',
},
generation: {
tabs: {
create: "创建",
saved: "已保存",
create: '创建',
saved: '已保存',
},
savedNoData: {
title: "您还没有保存结果!",
title: '您还没有保存结果!',
description: '开始生成内容,您可以在这里找到保存的结果。',
startCreateContent: '开始生成内容'
startCreateContent: '开始生成内容',
},
title: "AI 智能书写",
queryTitle: "查询内容",
queryPlaceholder: "请输入文本内容",
run: "运行",
copy: "拷贝",
resultTitle: "AI 书写",
noData: "AI 会在这里给你惊喜。",
title: 'AI 智能书写',
queryTitle: '查询内容',
queryPlaceholder: '请输入文本内容',
run: '运行',
copy: '拷贝',
resultTitle: 'AI 书写',
noData: 'AI 会在这里给你惊喜。',
},
};
}
export default translation;
export default translation

View File

@@ -1,16 +1,18 @@
import type { IOnCompleted, IOnData, IOnError } from './base'
import {
del as consoleDel, get as consoleGet, post as consolePost,
delPublic as del, getPublic as get, postPublic as post, ssePost,
del as consoleDel, get as consoleGet, patch as consolePatch, post as consolePost,
delPublic as del, getPublic as get, patchPublic as patch, postPublic as post, ssePost,
} from './base'
import type { Feedbacktype } from '@/app/components/app/chat'
function getAction(action: 'get' | 'post' | 'del', isInstalledApp: boolean) {
function getAction(action: 'get' | 'post' | 'del' | 'patch', isInstalledApp: boolean) {
switch (action) {
case 'get':
return isInstalledApp ? consoleGet : get
case 'post':
return isInstalledApp ? consolePost : post
case 'patch':
return isInstalledApp ? consolePatch : patch
case 'del':
return isInstalledApp ? consoleDel : del
}
@@ -55,8 +57,16 @@ export const fetchAppInfo = async () => {
return get('/site')
}
export const fetchConversations = async (isInstalledApp: boolean, installedAppId = '', last_id?: string) => {
return getAction('get', isInstalledApp)(getUrl('conversations', isInstalledApp, installedAppId), { params: { ...{ limit: 20 }, ...(last_id ? { last_id } : {}) } })
export const fetchConversations = async (isInstalledApp: boolean, installedAppId = '', last_id?: string, pinned?: boolean, limit?: number) => {
return getAction('get', isInstalledApp)(getUrl('conversations', isInstalledApp, installedAppId), { params: { ...{ limit: limit || 20 }, ...(last_id ? { last_id } : {}), ...(pinned !== undefined ? { pinned } : {}) } })
}
export const pinConversation = async (isInstalledApp: boolean, installedAppId = '', id: string) => {
return getAction('patch', isInstalledApp)(getUrl(`conversations/${id}/pin`, isInstalledApp, installedAppId))
}
export const unpinConversation = async (isInstalledApp: boolean, installedAppId = '', id: string) => {
return getAction('patch', isInstalledApp)(getUrl(`conversations/${id}/unpin`, isInstalledApp, installedAppId))
}
export const fetchChatList = async (conversationId: string, isInstalledApp: boolean, installedAppId = '') => {