Compare commits

..

1 Commits

Author SHA1 Message Date
Joe
4fc91d526e fix: dataset editor 2025-03-07 15:59:36 +08:00
10 changed files with 36 additions and 72 deletions

View File

@@ -5,6 +5,7 @@ on:
branches: branches:
- "main" - "main"
- "deploy/dev" - "deploy/dev"
- "fix/dataset-admin"
release: release:
types: [published] types: [published]

View File

@@ -9,7 +9,7 @@ class PackagingInfo(BaseSettings):
CURRENT_VERSION: str = Field( CURRENT_VERSION: str = Field(
description="Dify version", description="Dify version",
default="0.15.4", default="0.15.3",
) )
COMMIT_SHA: str = Field( COMMIT_SHA: str = Field(

View File

@@ -310,7 +310,7 @@ class DatasetInitApi(Resource):
@cloud_edition_billing_resource_check("vector_space") @cloud_edition_billing_resource_check("vector_space")
def post(self): def post(self):
# The role of the current user in the ta table must be admin, owner, or editor # The role of the current user in the ta table must be admin, owner, or editor
if not current_user.is_editor: if not current_user.is_dataset_editor:
raise Forbidden() raise Forbidden()
parser = reqparse.RequestParser() parser = reqparse.RequestParser()
@@ -684,7 +684,7 @@ class DocumentProcessingApi(DocumentResource):
document = self.get_document(dataset_id, document_id) document = self.get_document(dataset_id, document_id)
# The role of the current user in the ta table must be admin, owner, or editor # The role of the current user in the ta table must be admin, owner, or editor
if not current_user.is_editor: if not current_user.is_dataset_editor:
raise Forbidden() raise Forbidden()
if action == "pause": if action == "pause":
@@ -748,7 +748,7 @@ class DocumentMetadataApi(DocumentResource):
doc_metadata = req_data.get("doc_metadata") doc_metadata = req_data.get("doc_metadata")
# The role of the current user in the ta table must be admin, owner, or editor # The role of the current user in the ta table must be admin, owner, or editor
if not current_user.is_editor: if not current_user.is_dataset_editor:
raise Forbidden() raise Forbidden()
if doc_type is None or doc_metadata is None: if doc_type is None or doc_metadata is None:

View File

@@ -122,7 +122,7 @@ class DatasetDocumentSegmentListApi(Resource):
segment_ids = request.args.getlist("segment_id") segment_ids = request.args.getlist("segment_id")
# The role of the current user in the ta table must be admin or owner # The role of the current user in the ta table must be admin or owner
if not current_user.is_editor: if not current_user.is_dataset_editor:
raise Forbidden() raise Forbidden()
try: try:
DatasetService.check_dataset_permission(dataset, current_user) DatasetService.check_dataset_permission(dataset, current_user)
@@ -149,7 +149,7 @@ class DatasetDocumentSegmentApi(Resource):
# check user's model setting # check user's model setting
DatasetService.check_dataset_model_setting(dataset) DatasetService.check_dataset_model_setting(dataset)
# The role of the current user in the ta table must be admin, owner, or editor # The role of the current user in the ta table must be admin, owner, or editor
if not current_user.is_editor: if not current_user.is_dataset_editor:
raise Forbidden() raise Forbidden()
try: try:
@@ -202,7 +202,7 @@ class DatasetDocumentSegmentAddApi(Resource):
document = DocumentService.get_document(dataset_id, document_id) document = DocumentService.get_document(dataset_id, document_id)
if not document: if not document:
raise NotFound("Document not found.") raise NotFound("Document not found.")
if not current_user.is_editor: if not current_user.is_dataset_editor:
raise Forbidden() raise Forbidden()
# check embedding model setting # check embedding model setting
if dataset.indexing_technique == "high_quality": if dataset.indexing_technique == "high_quality":
@@ -277,7 +277,7 @@ class DatasetDocumentSegmentUpdateApi(Resource):
if not segment: if not segment:
raise NotFound("Segment not found.") raise NotFound("Segment not found.")
# The role of the current user in the ta table must be admin, owner, or editor # The role of the current user in the ta table must be admin, owner, or editor
if not current_user.is_editor: if not current_user.is_dataset_editor:
raise Forbidden() raise Forbidden()
try: try:
DatasetService.check_dataset_permission(dataset, current_user) DatasetService.check_dataset_permission(dataset, current_user)
@@ -320,7 +320,7 @@ class DatasetDocumentSegmentUpdateApi(Resource):
if not segment: if not segment:
raise NotFound("Segment not found.") raise NotFound("Segment not found.")
# The role of the current user in the ta table must be admin or owner # The role of the current user in the ta table must be admin or owner
if not current_user.is_editor: if not current_user.is_dataset_editor:
raise Forbidden() raise Forbidden()
try: try:
DatasetService.check_dataset_permission(dataset, current_user) DatasetService.check_dataset_permission(dataset, current_user)
@@ -420,7 +420,7 @@ class ChildChunkAddApi(Resource):
).first() ).first()
if not segment: if not segment:
raise NotFound("Segment not found.") raise NotFound("Segment not found.")
if not current_user.is_editor: if not current_user.is_dataset_editor:
raise Forbidden() raise Forbidden()
# check embedding model setting # check embedding model setting
if dataset.indexing_technique == "high_quality": if dataset.indexing_technique == "high_quality":
@@ -520,7 +520,7 @@ class ChildChunkAddApi(Resource):
if not segment: if not segment:
raise NotFound("Segment not found.") raise NotFound("Segment not found.")
# The role of the current user in the ta table must be admin, owner, or editor # The role of the current user in the ta table must be admin, owner, or editor
if not current_user.is_editor: if not current_user.is_dataset_editor:
raise Forbidden() raise Forbidden()
try: try:
DatasetService.check_dataset_permission(dataset, current_user) DatasetService.check_dataset_permission(dataset, current_user)
@@ -570,7 +570,7 @@ class ChildChunkUpdateApi(Resource):
if not child_chunk: if not child_chunk:
raise NotFound("Child chunk not found.") raise NotFound("Child chunk not found.")
# The role of the current user in the ta table must be admin or owner # The role of the current user in the ta table must be admin or owner
if not current_user.is_editor: if not current_user.is_dataset_editor:
raise Forbidden() raise Forbidden()
try: try:
DatasetService.check_dataset_permission(dataset, current_user) DatasetService.check_dataset_permission(dataset, current_user)
@@ -614,7 +614,7 @@ class ChildChunkUpdateApi(Resource):
if not child_chunk: if not child_chunk:
raise NotFound("Child chunk not found.") raise NotFound("Child chunk not found.")
# The role of the current user in the ta table must be admin or owner # The role of the current user in the ta table must be admin or owner
if not current_user.is_editor: if not current_user.is_dataset_editor:
raise Forbidden() raise Forbidden()
try: try:
DatasetService.check_dataset_permission(dataset, current_user) DatasetService.check_dataset_permission(dataset, current_user)

View File

@@ -195,7 +195,7 @@ class CodeNode(BaseNode[CodeNodeData]):
if output_config.type == "object": if output_config.type == "object":
# check if output is object # check if output is object
if not isinstance(result.get(output_name), dict): if not isinstance(result.get(output_name), dict):
if isinstance(result.get(output_name), type(None)): if result.get(output_name) is None:
transformed_result[output_name] = None transformed_result[output_name] = None
else: else:
raise OutputValidationError( raise OutputValidationError(
@@ -223,7 +223,7 @@ class CodeNode(BaseNode[CodeNodeData]):
elif output_config.type == "array[number]": elif output_config.type == "array[number]":
# check if array of number available # check if array of number available
if not isinstance(result[output_name], list): if not isinstance(result[output_name], list):
if isinstance(result[output_name], type(None)): if result[output_name] is None:
transformed_result[output_name] = None transformed_result[output_name] = None
else: else:
raise OutputValidationError( raise OutputValidationError(
@@ -244,7 +244,7 @@ class CodeNode(BaseNode[CodeNodeData]):
elif output_config.type == "array[string]": elif output_config.type == "array[string]":
# check if array of string available # check if array of string available
if not isinstance(result[output_name], list): if not isinstance(result[output_name], list):
if isinstance(result[output_name], type(None)): if result[output_name] is None:
transformed_result[output_name] = None transformed_result[output_name] = None
else: else:
raise OutputValidationError( raise OutputValidationError(
@@ -265,7 +265,7 @@ class CodeNode(BaseNode[CodeNodeData]):
elif output_config.type == "array[object]": elif output_config.type == "array[object]":
# check if array of object available # check if array of object available
if not isinstance(result[output_name], list): if not isinstance(result[output_name], list):
if isinstance(result[output_name], type(None)): if result[output_name] is None:
transformed_result[output_name] = None transformed_result[output_name] = None
else: else:
raise OutputValidationError( raise OutputValidationError(

View File

@@ -2,7 +2,7 @@ x-shared-env: &shared-api-worker-env
services: services:
# API service # API service
api: api:
image: langgenius/dify-api:0.15.4 image: langgenius/dify-api:0.15.3
restart: always restart: always
environment: environment:
# Use the shared environment variables. # Use the shared environment variables.
@@ -25,7 +25,7 @@ services:
# worker service # worker service
# The Celery worker for processing the queue. # The Celery worker for processing the queue.
worker: worker:
image: langgenius/dify-api:0.15.4 image: langgenius/dify-api:0.15.3
restart: always restart: always
environment: environment:
# Use the shared environment variables. # Use the shared environment variables.
@@ -47,7 +47,7 @@ services:
# Frontend web application. # Frontend web application.
web: web:
image: langgenius/dify-web:0.15.4 image: langgenius/dify-web:0.15.3
restart: always restart: always
environment: environment:
CONSOLE_API_URL: ${CONSOLE_API_URL:-} CONSOLE_API_URL: ${CONSOLE_API_URL:-}

View File

@@ -393,7 +393,7 @@ x-shared-env: &shared-api-worker-env
services: services:
# API service # API service
api: api:
image: langgenius/dify-api:0.15.4 image: langgenius/dify-api:0.15.3
restart: always restart: always
environment: environment:
# Use the shared environment variables. # Use the shared environment variables.
@@ -416,7 +416,7 @@ services:
# worker service # worker service
# The Celery worker for processing the queue. # The Celery worker for processing the queue.
worker: worker:
image: langgenius/dify-api:0.15.4 image: langgenius/dify-api:0.15.3
restart: always restart: always
environment: environment:
# Use the shared environment variables. # Use the shared environment variables.
@@ -438,7 +438,7 @@ services:
# Frontend web application. # Frontend web application.
web: web:
image: langgenius/dify-web:0.15.4 image: langgenius/dify-web:0.15.3
restart: always restart: always
environment: environment:
CONSOLE_API_URL: ${CONSOLE_API_URL:-} CONSOLE_API_URL: ${CONSOLE_API_URL:-}

View File

@@ -11,12 +11,10 @@ import { useLocalStorageState } from 'ahooks'
import produce from 'immer' import produce from 'immer'
import type { import type {
ChatConfig, ChatConfig,
ChatItem,
Feedback, Feedback,
} from '../types' } from '../types'
import { CONVERSATION_ID_INFO } from '../constants' import { CONVERSATION_ID_INFO } from '../constants'
import { buildChatItemTree, getProcessedInputsFromUrlParams } from '../utils' import { getPrevChatList, getProcessedInputsFromUrlParams } from '../utils'
import { getProcessedFilesFromResponse } from '../../file-uploader/utils'
import { import {
fetchAppInfo, fetchAppInfo,
fetchAppMeta, fetchAppMeta,
@@ -34,33 +32,6 @@ import { useToastContext } from '@/app/components/base/toast'
import { changeLanguage } from '@/i18n/i18next-config' import { changeLanguage } from '@/i18n/i18next-config'
import { InputVarType } from '@/app/components/workflow/types' import { InputVarType } from '@/app/components/workflow/types'
import { TransferMethod } from '@/types/app' import { TransferMethod } from '@/types/app'
import { addFileInfos, sortAgentSorts } from '@/app/components/tools/utils'
function getFormattedChatList(messages: any[]) {
const newChatList: ChatItem[] = []
messages.forEach((item) => {
const questionFiles = item.message_files?.filter((file: any) => file.belongs_to === 'user') || []
newChatList.push({
id: `question-${item.id}`,
content: item.query,
isAnswer: false,
message_files: getProcessedFilesFromResponse(questionFiles.map((item: any) => ({ ...item, related_id: item.id }))),
parentMessageId: item.parent_message_id || undefined,
})
const answerFiles = item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || []
newChatList.push({
id: item.id,
content: item.answer,
agent_thoughts: addFileInfos(item.agent_thoughts ? sortAgentSorts(item.agent_thoughts) : item.agent_thoughts, item.message_files),
feedback: item.feedback,
isAnswer: true,
citation: item.retriever_resources,
message_files: getProcessedFilesFromResponse(answerFiles.map((item: any) => ({ ...item, related_id: item.id }))),
parentMessageId: `question-${item.id}`,
})
})
return newChatList
}
export const useEmbeddedChatbot = () => { export const useEmbeddedChatbot = () => {
const isInstalledApp = false const isInstalledApp = false
@@ -106,7 +77,7 @@ export const useEmbeddedChatbot = () => {
const appPrevChatList = useMemo( const appPrevChatList = useMemo(
() => (currentConversationId && appChatListData?.data.length) () => (currentConversationId && appChatListData?.data.length)
? buildChatItemTree(getFormattedChatList(appChatListData.data)) ? getPrevChatList(appChatListData.data)
: [], : [],
[appChatListData, currentConversationId], [appChatListData, currentConversationId],
) )

View File

@@ -18,7 +18,7 @@ import ImageGallery from '@/app/components/base/image-gallery'
import { useChatContext } from '@/app/components/base/chat/chat/context' import { useChatContext } from '@/app/components/base/chat/chat/context'
import VideoGallery from '@/app/components/base/video-gallery' import VideoGallery from '@/app/components/base/video-gallery'
import AudioGallery from '@/app/components/base/audio-gallery' import AudioGallery from '@/app/components/base/audio-gallery'
// import SVGRenderer from '@/app/components/base/svg-gallery' import SVGRenderer from '@/app/components/base/svg-gallery'
import MarkdownButton from '@/app/components/base/markdown-blocks/button' import MarkdownButton from '@/app/components/base/markdown-blocks/button'
import MarkdownForm from '@/app/components/base/markdown-blocks/form' import MarkdownForm from '@/app/components/base/markdown-blocks/form'
@@ -118,13 +118,13 @@ const CodeBlock: CodeComponent = memo(({ inline, className, children, ...props }
</div> </div>
) )
} }
// else if (language === 'svg' && isSVG) { else if (language === 'svg' && isSVG) {
// return ( return (
// <ErrorBoundary> <ErrorBoundary>
// <SVGRenderer content={content} /> <SVGRenderer content={content} />
// </ErrorBoundary> </ErrorBoundary>
// ) )
// } }
else { else {
return ( return (
<SyntaxHighlighter <SyntaxHighlighter
@@ -224,16 +224,8 @@ const Link = ({ node, ...props }: any) => {
} }
} }
function escapeSVGTags(htmlString: string): string {
return htmlString.replace(/(<svg[\s\S]*?>)([\s\S]*?)(<\/svg>)/gi, (match: string, openTag: string, innerContent: string, closeTag: string): string => {
return openTag.replace(/</g, '&lt;').replace(/>/g, '&gt;')
+ innerContent.replace(/</g, '&lt;').replace(/>/g, '&gt;')
+ closeTag.replace(/</g, '&lt;').replace(/>/g, '&gt;')
})
}
export function Markdown(props: { content: string; className?: string }) { export function Markdown(props: { content: string; className?: string }) {
const latexContent = preprocessLaTeX(escapeSVGTags(props.content)) const latexContent = preprocessLaTeX(props.content)
return ( return (
<div className={cn(props.className, 'markdown-body')}> <div className={cn(props.className, 'markdown-body')}>
<ReactMarkdown <ReactMarkdown

View File

@@ -1,6 +1,6 @@
{ {
"name": "dify-web", "name": "dify-web",
"version": "0.15.4", "version": "0.15.3",
"private": true, "private": true,
"engines": { "engines": {
"node": ">=18.17.0" "node": ">=18.17.0"