Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 19 additions & 17 deletions addons/wiki/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def validate_page_name(value):
raise NameEmptyError('Page name cannot be blank.')
if value.find('/') != -1:
raise NameInvalidError('Page name cannot contain forward slashes.')
if len(value) > 100:
if len(value) > 200:
raise NameMaximumLengthError('Page name cannot be greater than 100 characters.')
return True

Expand Down Expand Up @@ -242,7 +242,7 @@ def get_absolute_url(self):

class WikiPageNodeManager(models.Manager):

def create_for_node(self, node, name, content, auth, parent=None, is_wiki_import=False):
def create_for_node(self, node, name, content, auth, parent=None, is_wiki_import=False, add_activity_log=True):
existing_wiki_page = WikiPage.objects.get_for_node(node, name)
if existing_wiki_page:
raise NodeStateError('Wiki Page already exists.')
Expand All @@ -255,7 +255,7 @@ def create_for_node(self, node, name, content, auth, parent=None, is_wiki_import
is_wiki_import=is_wiki_import
)
# Creates a WikiVersion object
wiki_page.update(auth.user, content, is_wiki_import=is_wiki_import)
wiki_page.update(auth.user, content, is_wiki_import=is_wiki_import, add_log=add_activity_log)
return wiki_page

def get_for_node(self, node, name=None, id=None):
Expand Down Expand Up @@ -312,29 +312,31 @@ def save(self, is_wiki_import=False, *args, **kwargs):
self.node.update_search(wiki_page=self)
return rv

def update(self, user, content, is_wiki_import=False):
def update(self, user, content, is_wiki_import=False, add_log=True):
"""
Updates the wiki with the provided content by creating a new version
:param user: The user that is updating the wiki
:param content: Latest content for wiki
:param add_log: Whether to add WIKI_UPDATED to the activity log (default True)
"""
version = WikiVersion(user=user, wiki_page=self, content=content, identifier=self.current_version_number + 1)
version.save(is_wiki_import=is_wiki_import)

self.node.add_log(
action=NodeLog.WIKI_UPDATED,
params={
'project': self.node.parent_id,
'node': self.node._primary_key,
'page': self.page_name,
'page_id': self._primary_key,
'version': version.identifier,
},
auth=Auth(user),
log_date=version.created,
save=True
)
if add_log:
self.node.add_log(
action=NodeLog.WIKI_UPDATED,
params={
'project': self.node.parent_id,
'node': self.node._primary_key,
'page': self.page_name,
'page_id': self._primary_key,
'version': version.identifier,
},
auth=Auth(user),
log_date=version.created,
save=True
)
return version

def update_active_sharejs(self, node):
Expand Down
20 changes: 17 additions & 3 deletions addons/wiki/templates/import_wiki_page.mako
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
## -*- coding: utf-8 -*-
<%def name="stylesheets()">
${parent.stylesheets()}
<link rel="stylesheet" href="/static/css/pages/wiki-page.css">
Expand Down Expand Up @@ -115,6 +116,15 @@
const WIKI_IMPORT_TIMEOUT = WIKI_IMPORT_INTERVAL * IMPORT_N;
const WIKI_IMPORT_OPERATION = 'import';
const VALIDATE_WIKI_IMPORT_OPERATION = 'validate';
const MAX_DISPLAY_NAME_LENGTH = 60; // Maximum number of characters to display

// Function to truncate file name for display
function truncateFileName(fileName, maxLength) {
if (!fileName || fileName.length <= maxLength) {
return fileName;
}
return fileName.substring(0, maxLength) + '...';
}

$wikiImportForm.on('submit', async function (e) {
e.preventDefault();
Expand Down Expand Up @@ -295,11 +305,15 @@
if (item.status === 'valid_exists') {
valid_exists_ctn++;
$alertInfoForm.find('.partOperationAll').css('display', '');
$('#validateInfo ul').append('<li>' + (item.path).slice(1) + '</li>')
$('#perFileDifinitionForm ul').append('<li id="' + (item.path).slice(1) + '" name="WikiImportOperationPerItem">' + '<div name="WikiImportOperationPerName">' + (item.path).slice(1) + '</div>' + selectOperation + '</li>');
var displayPath = (item.path).slice(1);
var truncatedPath = truncateFileName(displayPath, MAX_DISPLAY_NAME_LENGTH);
$('#validateInfo ul').append('<li title="' + displayPath + '">' + truncatedPath + '</li>')
$('#perFileDifinitionForm ul').append('<li id="' + (item.path).slice(1) + '" name="WikiImportOperationPerItem">' + '<div name="WikiImportOperationPerName" title="' + displayPath + '">' + truncatedPath + '</div>' + selectOperation + '</li>');
} else if (item.status === 'valid_duplicated'){
$('#attentionDuplicatedInfo').css('display', '');
$('#duplicatedInfo ul').append('<li>' + (item.path).slice(1) + '</li>')
var displayPath = (item.path).slice(1);
var truncatedPath = truncateFileName(displayPath, MAX_DISPLAY_NAME_LENGTH);
$('#duplicatedInfo ul').append('<li title="' + displayPath + '">' + truncatedPath + '</li>')
}
});
if (valid_exists_ctn === 0) {
Expand Down
4 changes: 2 additions & 2 deletions addons/wiki/templates/sort_wiki_page.mako
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<div class="modal-body sort-modal-body">
<h3 class="sort-title">${_("Wiki Tree")}</h3>
<div id="manageWikitree" class="scripted">
<ul class="sort-tree" data-bind="sortable: {template: 'wikitreeRow', data: $root.data, afterMove: $root.afterMove, beforeMove: $root.beforeMove}"></ul>
<ul class="sort-tree" data-bind="sortable: {template: 'wikitreeRow', data: $root.data, afterMove: $root.afterMove, beforeMove: $root.beforeMove, options: { dropOnEmpty: true } }"></ul>
</div>
</div><!-- end modal-body -->
<div class="modal-footer sort-modal-footer">
Expand All @@ -41,7 +41,7 @@
</div>
<!-- /ko -->
<!-- ko if: $data.children() -->
<ul class="sort-children" data-bind="sortable: { template: 'wikitreeRow', data: $data.children, afterMove: $root.afterMove, beforeMove: $root.beforeMove}"></ul>
<ul class="sort-children" data-bind="sortable: { template: 'wikitreeRow', data: $data.children, afterMove: $root.afterMove, beforeMove: $root.beforeMove, options: { dropOnEmpty: true }}"></ul>
<!-- /ko -->
</li>
</script>
2 changes: 1 addition & 1 deletion addons/wiki/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class TestWikiPageModel:

@pytest.mark.enable_implicit_clean
def test_page_name_cannot_be_greater_than_100_characters(self):
bad_name = 'a' * 101
bad_name = 'a' * 201
page = WikiPage(page_name=bad_name)
with pytest.raises(NameMaximumLengthError):
page.save()
Expand Down
2 changes: 1 addition & 1 deletion addons/wiki/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ def test_rename_new_name_invalid_special_characters(self):
self.second_wiki.rename(invalid_name, self.auth)

def test_rename_name_maximum_length(self):
new_name = 'a' * 101
new_name = 'a' * 201
with pytest.raises(NameMaximumLengthError):
self.second_wiki.rename(new_name, self.auth)

Expand Down
4 changes: 2 additions & 2 deletions addons/wiki/tests/test_wiki_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def test_create_for_node_true(self, mock_create):

# True?
mock_create.assert_called_with(is_wiki_import=True, node=self.project, page_name='home child', parent=None, user=self.user)
wiki_page.update.assert_called_with(self.user, 'home child content', is_wiki_import=True)
wiki_page.update.assert_called_with(self.user, 'home child content', add_log=True, is_wiki_import=True)

@mock.patch('addons.wiki.models.WikiPage.objects.create')
def test_create_for_node_false(self, mock_create):
Expand All @@ -142,7 +142,7 @@ def test_create_for_node_false(self, mock_create):

# False
mock_create.assert_called_with(is_wiki_import=False, node=self.project, page_name='home child', parent=None, user=self.user)
wiki_page.update.assert_called_with(self.user, 'home child content', is_wiki_import=False)
wiki_page.update.assert_called_with(self.user, 'home child content', add_log=True, is_wiki_import=False)

def test_create(self):
new_node = WikiPage.objects.create(
Expand Down
6 changes: 6 additions & 0 deletions addons/wiki/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from django.core.exceptions import ObjectDoesNotExist
from django.utils import timezone
from framework.exceptions import HTTPError
from framework.auth import Auth
from framework.auth.utils import privacy_info_handle
from framework.auth.decorators import must_be_logged_in
from framework.auth.core import get_current_user_id
Expand Down Expand Up @@ -618,6 +619,11 @@ def format_project_wiki_pages(node, auth):
pages = []
can_edit = node.has_permission(auth.user, WRITE) and not node.is_registration
project_wiki_pages = _get_wiki_pages_latest(node)
# ホームが存在せず、編集可能な場合は自動作成(Reorder Wiki Tree で表示するため)
# add_activity_log=False: Wikiタブを開いただけの自動作成ではアクティビティログに残さない
if (can_edit and auth.user and
not WikiPage.objects.get_for_node(node, 'home')):
WikiPage.objects.create_for_node(node, 'home', '', Auth(auth.user), add_activity_log=False)
home_wiki_page = format_home_wiki_page(node)
pages.append(home_wiki_page)
for wiki_page in project_wiki_pages:
Expand Down
148 changes: 148 additions & 0 deletions website/static/css/pages/wiki-page.css
Original file line number Diff line number Diff line change
Expand Up @@ -532,4 +532,152 @@ li[name="WikiImportOperationPerItem"] {
.milkdown td {
border: 1px solid #ccc;
padding: 8px;
}

/* Hide collaborativeStatus and cp-sidebar-content by default */
.cp-sidebar-content {
display: none !important;
visibility: hidden !important;
height: 0 !important;
overflow: hidden !important;
}

/* Ensure icons are visible in wiki tree */
.tb-expand-icon-holder,
.tb-expand-icon-holder > i,
.tb-expand-icon-holder > span {
display: inline-block !important;
visibility: visible !important;
opacity: 1 !important;
}

/* Fix icon and file name alignment in wiki tree */
#grid .tb-expand-icon-holder,
#grid .tb-expand-icon-holder > i,
#grid .tb-expand-icon-holder > span,
#grid .tb-row .tb-td .fg-file-links {
vertical-align: middle !important;
}

/* Fix icon vertical position (method 3: nudge icon up to align with text) */
#grid .tb-expand-icon-holder > i,
#grid .tb-expand-icon-holder > span {
position: relative !important;
top: -2px !important;
}

/* Fix long file names in wiki tree - truncate with ellipsis */
.tb-row .tb-td {
overflow: visible !important;
}

.tb-row .tb-td .fg-file-links {
overflow: hidden !important;
text-overflow: ellipsis !important;
white-space: nowrap !important;
display: inline-block !important;
max-width: calc(100% - 30px) !important;
}

/* Fix long file names in wiki import modal - truncate with ellipsis */
#alertInfo #validateInfo ul,
#alertInfo #duplicatedInfo ul,
#alertInfo #duplicatedFolder ul {
padding-left: 20px !important;
margin: 0 !important;
list-style: none !important;
}

#alertInfo #validateInfo ul li,
#alertInfo #duplicatedInfo ul li,
#alertInfo #duplicatedFolder ul li {
overflow: hidden !important;
text-overflow: ellipsis !important;
display: -webkit-box !important;
-webkit-line-clamp: 2 !important;
-webkit-box-orient: vertical !important;
max-width: 100% !important;
position: relative !important;
padding-left: 15px !important;
margin-left: 0 !important;
cursor: help !important;
word-wrap: break-word !important;
word-break: break-word !important;
line-height: 1.5 !important;
height: auto !important;
max-height: none !important;
}

#alertInfo #validateInfo ul li::before,
#alertInfo #duplicatedInfo ul li::before,
#alertInfo #duplicatedFolder ul li::before {
content: "・" !important;
position: absolute !important;
left: 0 !important;
display: inline-block !important;
width: 15px !important;
}

#alertInfo #perFileDifinitionForm ul {
padding-left: 0 !important;
margin: 0 !important;
}

#alertInfo #perFileDifinitionForm ul li {
display: flex !important;
align-items: flex-start !important;
justify-content: space-between !important;
overflow: visible !important;
width: 100% !important;
box-sizing: border-box !important;
padding: 8px 0 !important;
margin: 0 !important;
list-style: none !important;
position: relative !important;
padding-left: 0 !important;
}

#alertInfo #perFileDifinitionForm ul li::before {
content: "・" !important;
position: absolute !important;
left: 5px !important;
top: 8px !important;
display: inline-block !important;
width: auto !important;
line-height: 1.5 !important;
margin-right: 0 !important;
}

#alertInfo #perFileDifinitionForm ul li div[name="WikiImportOperationPerName"] {
overflow: hidden !important;
text-overflow: ellipsis !important;
display: -webkit-box !important;
-webkit-line-clamp: 2 !important;
-webkit-box-orient: vertical !important;
flex: 1 1 auto !important;
min-width: 0 !important;
max-width: calc(100% - 160px) !important;
margin-right: 30px !important;
margin-left: -30px !important;
cursor: help !important;
word-wrap: break-word !important;
word-break: break-word !important;
line-height: 1.5 !important;
align-self: flex-start !important;
}

#alertInfo #perFileDifinitionForm ul li div[name="WikiImportOperationPer"] {
flex: 0 0 auto !important;
min-width: 120px !important;
max-width: 130px !important;
width: 130px !important;
margin-left: auto !important;
align-self: center !important;
margin-top: 0 !important;
}

#alertInfo #perFileDifinitionForm ul li div[name="WikiImportOperationPer"] .form-control {
width: 100% !important;
min-width: 120px !important;
max-width: 130px !important;
}
Loading