diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json index 038aaeee..e46a25da 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/SeederData.json @@ -643,6 +643,18 @@ "en": "Topic Management", "tr": "Konu Yönetimi" }, + { + "resourceName": "Platform", + "key": "App.Forum.TopicManagement.Baslik", + "en": "Topic", + "tr": "Konu" + }, + { + "resourceName": "Platform", + "key": "App.Forum.TopicManagement.Content", + "en": "Content", + "tr": "İçerik" + }, { "resourceName": "Platform", "key": "App.Forum.TopicManagement.NewTopic", @@ -697,6 +709,30 @@ "en": "Post Management", "tr": "Yazı Yönetimi" }, + { + "resourceName": "Platform", + "key": "App.Forum.PostManagement.BaslikEdit", + "en": "Your Reply", + "tr": "Cevabınız" + }, + { + "resourceName": "Platform", + "key": "App.Forum.PostManagement.BaslikNew", + "en": "Message", + "tr": "İçerik" + }, + { + "resourceName": "Platform", + "key": "App.Forum.PostManagement.MessageEdit", + "en": "Write your reply...", + "tr": "Cevabınızı yazın..." + }, + { + "resourceName": "Platform", + "key": "App.Forum.PostManagement.MessageNew", + "en": "Write your message...", + "tr": "Mesajınızı yazın..." + }, { "resourceName": "Platform", "key": "App.Forum.PostManagement.NewPost", @@ -844,7 +880,7 @@ { "resourceName": "Platform", "key": "DeleteConfirmation", - "en": "Silmek istediğinize emin misiniz?", + "en": "Are you sure you want to delete?", "tr": "Silmek istediğinize emin misiniz?" }, { @@ -2685,7 +2721,7 @@ }, { "resourceName": "Platform", - "key": "Sirket", + "key": "Organization", "en": "Organization", "tr": "Kurum" }, diff --git a/ui/dev-dist/sw.js b/ui/dev-dist/sw.js index db7285b5..5fdb83ae 100644 --- a/ui/dev-dist/sw.js +++ b/ui/dev-dist/sw.js @@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict'; "revision": "3ca0b8505b4bec776b69afdba2768812" }, { "url": "index.html", - "revision": "0.ru7ltd9thg8" + "revision": "0.kii9phg4rp8" }], {}); workbox.cleanupOutdatedCaches(); workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { diff --git a/ui/src/views/auth/Login.tsx b/ui/src/views/auth/Login.tsx index 119c490a..8af1fe5f 100644 --- a/ui/src/views/auth/Login.tsx +++ b/ui/src/views/auth/Login.tsx @@ -225,11 +225,11 @@ const Login = () => { {isMultiTenant && ( <>
setTenantName(e.target.value)} style={tenantStyle} diff --git a/ui/src/views/blog/BlogManagement.tsx b/ui/src/views/blog/BlogManagement.tsx deleted file mode 100644 index d36bbe59..00000000 --- a/ui/src/views/blog/BlogManagement.tsx +++ /dev/null @@ -1,881 +0,0 @@ -import React, { useState, useEffect } from 'react' -import Card from '@/components/ui/Card' -import Button from '@/components/ui/Button' -import Table from '@/components/ui/Table' -import Tag from '@/components/ui/Tag' -import Dialog from '@/components/ui/Dialog' -import { FormContainer, FormItem } from '@/components/ui/Form' -import Input from '@/components/ui/Input' -import Select from '@/components/ui/Select' -import Switcher from '@/components/ui/Switcher' -import { HiPlus, HiPencil, HiTrash, HiEye } from 'react-icons/hi' -import { useNavigate } from 'react-router-dom' -import { - blogService, -} from '@/services/blog.service' -import { format } from 'date-fns' -import { tr } from 'date-fns/locale' -import { Field, FieldProps, Form, Formik } from 'formik' -import * as Yup from 'yup' -import toast from '@/components/ui/toast' -import Notification from '@/components/ui/Notification' -import ReactQuill from 'react-quill' -import 'react-quill/dist/quill.snow.css' -import Tr from '@/components/ui/Table/Tr' -import Th from '@/components/ui/Table/Th' -import THead from '@/components/ui/Table/THead' -import TBody from '@/components/ui/Table/TBody' -import Td from '@/components/ui/Table/Td' -import { SelectBoxOption } from '@/shared/types' -import { Checkbox, Tabs } from '@/components/ui' -import { Helmet } from 'react-helmet' -import { useLocalization } from '@/utils/hooks/useLocalization' -import { ConfirmDialog } from '@/components/shared' -import { useStoreState } from '@/store/store' -import TabList from '@/components/ui/Tabs/TabList' -import TabNav from '@/components/ui/Tabs/TabNav' -import TabContent from '@/components/ui/Tabs/TabContent' -import { BlogCategory, BlogPost, CreateUpdateBlogCategoryDto, CreateUpdateBlogPostDto } from '@/proxy/blog/blog' - -const validationSchema = Yup.object().shape({ - title: Yup.string().required(), - summary: Yup.string().required(), - categoryId: Yup.string().required(), - content: Yup.string(), - tags: Yup.string(), - coverImage: Yup.string(), - isPublished: Yup.bool(), -}) - -const categoryValidationSchema = Yup.object().shape({ - name: Yup.string().required(), - slug: Yup.string().required(), - description: Yup.string(), - icon: Yup.string(), - displayOrder: Yup.number(), - isActive: Yup.bool(), -}) - -const BlogManagement = () => { - const { translate } = useLocalization() - const navigate = useNavigate() - const [activeTab, setActiveTab] = useState<'posts' | 'categories'>('posts') - const [posts, setPosts] = useState([]) - const [categories, setCategories] = useState([]) - const [loading, setLoading] = useState(false) - const [modalVisible, setModalVisible] = useState(false) - const [categoryModalVisible, setCategoryModalVisible] = useState(false) - const [editingPost, setEditingPost] = useState(null) - const [editingCategory, setEditingCategory] = useState(null) - const { texts } = useStoreState((state) => state.abpConfig) - const categoryItems = categories?.map((cat) => ({ - value: cat.id, - label: texts?.Platform[cat.name] + ' (' + cat.name + ')', - })) - - useEffect(() => { - loadData() - }, []) - - const loadData = async () => { - setLoading(true) - try { - const [postsData, categoriesData] = await Promise.all([ - blogService.getPosts({ pageSize: 100 }), - blogService.getCategories(), - ]) - setCategories(categoriesData) - setPosts(postsData.items) - } catch (error) { - toast.push( - - {translate('::Error:Loading')} - , - { - placement: 'top-center', - }, - ) - } finally { - setLoading(false) - } - } - - const handleCreate = () => { - setEditingPost(null) - setModalVisible(true) - } - - const handleEdit = (post: BlogPost) => { - setEditingPost(post) - setModalVisible(true) - } - - const handleDelete = async (id: string) => { - try { - await blogService.deletePost(id) - toast.push( - - {translate('::KayitSilindi')} - , - { - placement: 'top-center', - }, - ) - loadData() - } catch (error) { - toast.push( - - {translate('::Error:Deleting')} - , - { - placement: 'top-center', - }, - ) - } - } - - const handleSubmit = async (values: any, { setSubmitting }: any) => { - try { - const data: CreateUpdateBlogPostDto = { - title: values.title, - slug: values.slug, - contentTr: values.contentTr, - contentEn: values.contentEn, - summary: values.summary, - categoryId: values.categoryId, - tags: values.tags ? values.tags.split(',').map((t: string) => t.trim()) : [], - coverImage: values.coverImage, - isPublished: values.isPublished, - } - - if (editingPost) { - await blogService.updatePost(editingPost.id, data) - toast.push( - - {translate('::KayitGuncellendi')} - , - { - placement: 'top-center', - }, - ) - } else { - await blogService.createPost(data) - toast.push( - - {translate('::KayitEklendi')} - , - { - placement: 'top-center', - }, - ) - } - - setModalVisible(false) - loadData() - } catch (error) { - toast.push( - - {translate('::IslemBasarisiz')} - , - { - placement: 'top-center', - }, - ) - } finally { - setSubmitting(false) - } - } - - const handlePublish = async (post: BlogPost) => { - try { - if (post.isPublished) { - await blogService.unpublishPost(post.id) - toast.push( - - {translate('::YayinKaldirildi')} - , - { - placement: 'top-center', - }, - ) - } else { - await blogService.publishPost(post.id) - toast.push( - - {translate('::Yayinlandi')} - , - { - placement: 'top-center', - }, - ) - } - loadData() - } catch (error) { - toast.push( - - {translate('::IslemBasarisiz')} - , - { - placement: 'top-center', - }, - ) - } - } - - // Category functions - const handleCreateCategory = () => { - setEditingCategory(null) - setCategoryModalVisible(true) - } - - const handleEditCategory = (category: BlogCategory) => { - setEditingCategory(category) - //console.log(category) - setCategoryModalVisible(true) - } - - const handleDeleteCategory = async (id: string) => { - try { - await blogService.deleteCategory(id) - toast.push( - - {translate('::KayitSilindi')} - , - { - placement: 'top-center', - }, - ) - loadData() - } catch (error) { - toast.push( - - {translate('::IslemBasarisiz')} - , - { - placement: 'top-center', - }, - ) - } - } - - const handleSubmitCategory = async (values: any, { setSubmitting }: any) => { - try { - const data: CreateUpdateBlogCategoryDto = { - name: values.name, - slug: values.slug, - description: values.description, - icon: values.icon, - displayOrder: values.displayOrder, - isActive: values.isActive, - } - - if (editingCategory) { - await blogService.updateCategory(editingCategory.id, data) - toast.push( - - {translate('::KayitGuncellendi')} - , - { - placement: 'top-center', - }, - ) - } else { - await blogService.createCategory(data) - toast.push( - - {translate('::KayitEklendi')} - , - { - placement: 'top-center', - }, - ) - } - - setCategoryModalVisible(false) - loadData() - } catch (error) { - toast.push( - - {translate('::IslemBasarisiz')} - , - { - placement: 'top-center', - }, - ) - } finally { - setSubmitting(false) - } - } - - const initialValues = editingPost - ? { - title: editingPost.title, - slug: editingPost.slug, - summary: editingPost.summary, - contentTr: editingPost.contentTr, - contentEn: editingPost.contentEn, - categoryId: editingPost.category.id, - tags: editingPost.tags.join(', '), - coverImage: editingPost.coverImage || '', - isPublished: editingPost.isPublished, - } - : { - title: '', - slug: '', - summary: '', - content: '', - categoryId: '', - tags: '', - coverImage: '', - isPublished: false, - } - - const initialCategoryValues = editingCategory - ? { - name: editingCategory.name, - slug: editingCategory.slug, - description: editingCategory.description || '', - icon: editingCategory.icon, - displayOrder: editingCategory.displayOrder, - isActive: editingCategory.isActive, - } - : { - name: '', - slug: '', - description: '', - icon: '', - displayOrder: 0, - isActive: true, - } - - const [confirmDeletePost, setConfirmDeletePost] = useState(null) - const [confirmDeleteCategory, setConfirmDeleteCategory] = useState(null) - - const askDeletePost = (post: BlogPost) => { - setConfirmDeletePost(post) - } - - const askDeleteCategory = (category: BlogCategory) => { - setConfirmDeleteCategory(category) - } - - return ( - <> - - -
- - -
- - {activeTab === 'posts' ? ( - - - - - - - - - - - - - - {loading ? ( - - - - ) : ( - posts.map((post) => ( - - - - - - - - - - )) - )} - -
{translate('::blog.posts.post.title')}{translate('::blog.posts.post.slug')}{translate('::blog.posts.post.category')}{translate('::blog.posts.post.author')}{translate('::blog.posts.post.publishDate')}{translate('::blog.posts.post.status')} - {' '} - -
- {translate('::Loading')} -
{texts?.Platform[post.title]}{post.slug}{texts?.Platform[post.category?.name]}{post.author?.name} - {post.publishedAt - ? format(new Date(post.publishedAt), 'dd MMM yyyy', { locale: tr }) - : '-'} - - handlePublish(post)} - /> - -
-
-
- ) : ( - - - - - - - - - - - - - - {loading ? ( - - - - ) : ( - categories.map((category) => ( - - - - - - - - - - )) - )} - -
{translate('::blog.posts.categories.name')}{translate('::blog.posts.categories.slug')}{translate('::blog.posts.categories.description')}{translate('::blog.posts.categories.count')}{translate('::blog.posts.categories.order')}{translate('::blog.posts.categories.status')} - -
- {translate('::Loading')} -
{texts?.Platform[category.name]}{category.slug}{texts?.Platform[category.description!!]}{category.postCount}{category.displayOrder} - - {category.isActive ? 'Aktif' : 'Pasif'} - - -
-
-
- )} -
- - {/* Post Modal */} - setModalVisible(false)} - onRequestClose={() => setModalVisible(false)} - width={1000} - > -
- {editingPost ? translate('::blog.posts.edittitle') : translate('::blog.posts.newtitle')} -
- - - {({ values, touched, errors, isSubmitting, setFieldValue }) => ( -
- - - - {({ field, form }: FieldProps) => { - const options = texts?.Platform - ? Object.entries(texts.Platform).map(([key, value]) => ({ - value: key, - label: value + ' (' + key + ')', - })).filter(a=> a.value.startsWith("blog")) - : [] - - return ( - opt.value === field.value)} - onChange={(option) => form.setFieldValue(field.name, option?.value || '')} - /> - ) - }} - - - - - - {({ field, form }: FieldProps) => ( - opt.value === field.value)} - onChange={(option) => form.setFieldValue(field.name, option?.value || '')} - /> - ) - }} - - - - - - - - - - {({ field, form }: FieldProps) => { - const options = texts?.Platform - ? Object.entries(texts.Platform).map(([key, value]) => ({ - value: key, - label: value + ' (' + key + ')', - })) - : [] - - return ( - setFormData({ ...formData, name: e.target.value })} - className="w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-transparent" - required - /> -
-
- - setFormData({ ...formData, slug: e.target.value })} - className="w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-transparent" - required - /> -
- -
- -