From 261c3a75103208f747f86c2cbdbf6123a67d0666 Mon Sep 17 00:00:00 2001
From: Michael An <2331806369@qq.com>
Date: Wed, 29 May 2024 20:28:46 +0800
Subject: [PATCH] change wikis list style (#6125)
---
.../wiki-card-view/wiki-card-group.js | 40 ++++++
.../wiki-card-view/wiki-card-item.js | 132 ++++++++++++++++++
.../wiki-card-view/wiki-card-view.css | 93 ++++++++++++
.../wiki-card-view/wiki-card-view.js | 63 +++++++++
frontend/src/pages/wikis/wikis.js | 18 +--
5 files changed, 338 insertions(+), 8 deletions(-)
create mode 100644 frontend/src/components/wiki-card-view/wiki-card-group.js
create mode 100644 frontend/src/components/wiki-card-view/wiki-card-item.js
create mode 100644 frontend/src/components/wiki-card-view/wiki-card-view.css
create mode 100644 frontend/src/components/wiki-card-view/wiki-card-view.js
diff --git a/frontend/src/components/wiki-card-view/wiki-card-group.js b/frontend/src/components/wiki-card-view/wiki-card-group.js
new file mode 100644
index 0000000000..1466f3c813
--- /dev/null
+++ b/frontend/src/components/wiki-card-view/wiki-card-group.js
@@ -0,0 +1,40 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { gettext, username } from '../../utils/constants';
+import WikiCardItem from './wiki-card-item';
+
+const propTypes = {
+ wikis: PropTypes.array.isRequired,
+ deleteWiki: PropTypes.func.isRequired,
+ owner: PropTypes.string.isRequired,
+};
+
+class WikiCardGroup extends Component {
+ render() {
+ let { wikis, owner } = this.props;
+ return (
+
+
+
+ {username === owner ? gettext('My Wikis') : wikis[0].owner_nickname}
+
+
+ {wikis.map((wiki, index) => {
+ return (
+
+ );
+ })}
+
+
+ );
+ }
+}
+
+WikiCardGroup.propTypes = propTypes;
+
+export default WikiCardGroup;
diff --git a/frontend/src/components/wiki-card-view/wiki-card-item.js b/frontend/src/components/wiki-card-view/wiki-card-item.js
new file mode 100644
index 0000000000..c19c84b4cc
--- /dev/null
+++ b/frontend/src/components/wiki-card-view/wiki-card-item.js
@@ -0,0 +1,132 @@
+import React, { Component } from 'react';
+import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
+import PropTypes from 'prop-types';
+import moment from 'moment';
+import { siteRoot, gettext, appAvatarURL, username } from '../../utils/constants';
+import ModalPortal from '../modal-portal';
+import WikiDeleteDialog from '../dialog/wiki-delete-dialog';
+
+const propTypes = {
+ owner: PropTypes.string.isRequired,
+ wiki: PropTypes.object.isRequired,
+ deleteWiki: PropTypes.func.isRequired,
+};
+
+class WikiCardItem extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ isShowDeleteDialog: false,
+ isItemMenuShow: false,
+ };
+ }
+
+ onDeleteToggle = (e) => {
+ e.preventDefault();
+ this.setState({
+ isShowDeleteDialog: !this.state.isShowDeleteDialog,
+ });
+ };
+
+ onDeleteCancel = () => {
+ this.setState({
+ isShowDeleteDialog: !this.state.isShowDeleteDialog,
+ });
+ };
+
+ deleteWiki = () => {
+ let wiki = this.props.wiki;
+ this.props.deleteWiki(wiki);
+ this.setState({
+ isShowDeleteDialog: !this.state.isShowDeleteDialog,
+ });
+ };
+
+ clickWikiCard = (link) => {
+ window.open(link);
+ };
+
+ toggleDropDownMenu = () => {
+ this.setState({isItemMenuShow: !this.state.isItemMenuShow});
+ };
+
+ onClickDropdown = (e) => {
+ e.preventDefault();
+ e.stopPropagation();
+ };
+
+ renderAvatar = () => {
+ const { wiki } = this.props;
+ // const userProfileURL = `${siteRoot}profile/${encodeURIComponent(wiki.owner)}/`;
+ return (
+
+

+
{wiki.owner_nickname}
+
+ );
+ };
+
+ renderDept = () => {
+ const { wiki } = this.props;
+ return (
+
+
+ {wiki.owner_nickname}
+
+ );
+ };
+
+ render() {
+ const { owner, wiki } = this.props;
+ let isOldVersion = wiki.version !== 'v2';
+ let publishedUrl = `${siteRoot}published/${encodeURIComponent(wiki.slug)}/`;
+ let editUrl = `${siteRoot}wikis/${wiki.id}/`;
+ let wikiName = isOldVersion ? <>{wiki.name} (old version)> : <>{wiki.name}>;
+ return (
+ <>
+
+
+
+
+ {wikiName}
+
+
+
+
+ {/* {gettext('Rename')} */}
+ {gettext('Unpublish')}
+
+
+
+
+ {owner === username ? this.renderAvatar() : this.renderDept()}
+ {moment(wiki.updated_at).fromNow()}
+
+
+ {this.state.isShowDeleteDialog &&
+
+
+
+ }
+ >
+ );
+ }
+}
+
+WikiCardItem.propTypes = propTypes;
+
+export default WikiCardItem;
diff --git a/frontend/src/components/wiki-card-view/wiki-card-view.css b/frontend/src/components/wiki-card-view/wiki-card-view.css
new file mode 100644
index 0000000000..a074ae77c0
--- /dev/null
+++ b/frontend/src/components/wiki-card-view/wiki-card-view.css
@@ -0,0 +1,93 @@
+.wiki-card-group-items {
+ display: grid;
+ grid-template-columns: 32.5% 32.5% 32.5%;
+ gap: 16px 16px;
+}
+
+.wiki-card-item {
+ height: 120px;
+ width: 100%;
+ border: 1px solid #EEEEEE;
+ padding: 20px;
+ border-radius: 6px;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ cursor: pointer;
+}
+
+.wiki-card-item:hover {
+ border: 1px solid #DBDBDB;
+}
+
+.wiki-card-item .wiki-card-item-top,
+.wiki-card-item .wiki-card-item-bottom {
+ display: flex;
+ justify-content: space-between;
+}
+
+.wiki-card-item .wiki-item-updated-time {
+ font-size: 12px;
+ color: #666;
+}
+
+.wiki-card-item .wiki-card-item-top .sf3-font-wiki.sf3-font {
+ color: #FF8900;
+ font-size: 24px;
+}
+
+.wiki-card-item .wiki-card-item-top .wiki-card-item-name {
+ max-width: 250px;
+ font-size: 16px;
+}
+
+.wiki-card-item .wiki-card-item-top .dropdown .sf-dropdown-toggle {
+ border: 1px solid #dbdbdb;
+ padding: 2px 4px;
+ border-radius: 3px;
+ opacity: 0;
+ color: #444;
+}
+
+.wiki-card-item:hover .wiki-card-item-top .dropdown .sf-dropdown-toggle {
+ opacity: 1;
+}
+
+.wiki-card-item:hover .wiki-card-item-top .dropdown .sf-dropdown-toggle:hover {
+ background-color: #f5f5f5;
+}
+
+.wiki-card-item .wiki-card-item-avatar-container {
+ height: 20px;
+ display: flex;
+ align-items: center;
+ border: 1px solid #EEEEEE;
+ border-radius: 10px;
+ padding: 2px;
+}
+
+.wiki-card-item .wiki-card-item-avatar-container .avatar {
+ width: 16px;
+ height: 16px;
+}
+
+.wiki-card-item .wiki-card-item-avatar-container span {
+ font-size: 13px;
+}
+
+.wiki-card-item .wiki-card-item-avatar-container .sf3-font-department {
+ font-size: 1rem;
+ line-height: 1;
+ color: #999;
+}
+
+@media (max-width: 768px) {
+ .wiki-card-group-items {
+ display: grid;
+ grid-template-columns: 100%;
+ }
+ .wiki-card-item .wiki-card-item-top .dropdown .sf-dropdown-toggle {
+ border: none;
+ opacity: 1;
+ }
+}
diff --git a/frontend/src/components/wiki-card-view/wiki-card-view.js b/frontend/src/components/wiki-card-view/wiki-card-view.js
new file mode 100644
index 0000000000..771cdd8752
--- /dev/null
+++ b/frontend/src/components/wiki-card-view/wiki-card-view.js
@@ -0,0 +1,63 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { username } from '../../utils/constants';
+import WikiCardGroup from './wiki-card-group';
+import './wiki-card-view.css';
+
+const propTypes = {
+ data: PropTypes.object.isRequired,
+ deleteWiki: PropTypes.func.isRequired,
+};
+
+class WikiCardView extends Component {
+
+ classifyWikis = (wikis) => {
+ let myWikis = [];
+ let department2WikisMap = {};
+ for (let i = 0; i < wikis.length; i++) {
+ if (wikis[i].owner === username) {
+ myWikis.push(wikis[i]);
+ continue;
+ }
+ if (!department2WikisMap[wikis[i].owner]) {
+ department2WikisMap[wikis[i].owner] = [];
+ }
+ department2WikisMap[wikis[i].owner].push(wikis[i]);
+ }
+ return { department2WikisMap, myWikis };
+ };
+
+ render() {
+ let { loading, errorMsg, wikis } = this.props.data;
+
+ if (loading) {
+ return ;
+ }
+ if (errorMsg) {
+ return {errorMsg}
;
+ }
+ const { myWikis, department2WikisMap } = this.classifyWikis(wikis);
+ let wikiCardGroups = [];
+ wikiCardGroups.push(
+
+ );
+ for (let key in department2WikisMap) {
+ wikiCardGroups.push(
+
+ );
+ }
+ return wikiCardGroups;
+ }
+}
+
+WikiCardView.propTypes = propTypes;
+
+export default WikiCardView;
diff --git a/frontend/src/pages/wikis/wikis.js b/frontend/src/pages/wikis/wikis.js
index c774a35fde..1546dd8a19 100644
--- a/frontend/src/pages/wikis/wikis.js
+++ b/frontend/src/pages/wikis/wikis.js
@@ -9,8 +9,8 @@ import ModalPortal from '../../components/modal-portal';
import EmptyTip from '../../components/empty-tip';
import CommonToolbar from '../../components/toolbar/common-toolbar';
import AddWikiDialog from '../../components/dialog/add-wiki-dialog';
-import WikiListView from '../../components/wiki-list-view/wiki-list-view';
import wikiAPI from '../../utils/wiki-api';
+import WikiCardView from '../../components/wiki-card-view/wiki-card-view';
const propTypes = {
onShowSidePanel: PropTypes.func.isRequired,
@@ -156,22 +156,24 @@ class Wikis extends Component {
{gettext('Wikis')}
-
- {(this.state.loading || this.state.wikis.length !== 0) &&
-
+
- }
- {(!this.state.loading && this.state.wikis.length === 0) &&
+
+ }
+ {(!this.state.loading && this.state.wikis.length === 0) &&
+
{gettext('No Wikis')}
{gettext('You have not any wikis yet.')}
{gettext('A wiki can be accessed by anyone, not only users, via its URL.')}
{gettext('You can add a wiki by clicking the "Add Wiki" button in the menu bar.')}
- }
-
+
+ }