usage limits for rooms and convos
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,6 @@
|
|||||||
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify, send_file
|
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify, send_file
|
||||||
from flask_login import login_required, current_user
|
from flask_login import login_required, current_user
|
||||||
from models import db, Conversation, User, Message, MessageAttachment
|
from models import db, Conversation, User, Message, MessageAttachment, DocuPulseSettings
|
||||||
from forms import ConversationForm
|
from forms import ConversationForm
|
||||||
from routes.auth import require_password_change
|
from routes.auth import require_password_change
|
||||||
from utils import log_event, create_notification, get_unread_count
|
from utils import log_event, create_notification, get_unread_count
|
||||||
@@ -55,7 +55,8 @@ def conversations():
|
|||||||
query = query.filter(Conversation.name.ilike(f'%{search}%'))
|
query = query.filter(Conversation.name.ilike(f'%{search}%'))
|
||||||
conversations = query.order_by(Conversation.created_at.desc()).all()
|
conversations = query.order_by(Conversation.created_at.desc()).all()
|
||||||
unread_count = get_unread_count(current_user.id)
|
unread_count = get_unread_count(current_user.id)
|
||||||
return render_template('conversations/conversations.html', conversations=conversations, search=search, unread_notifications=unread_count)
|
usage_stats = DocuPulseSettings.get_usage_stats()
|
||||||
|
return render_template('conversations/conversations.html', conversations=conversations, search=search, unread_notifications=unread_count, usage_stats=usage_stats)
|
||||||
|
|
||||||
@conversations_bp.route('/create', methods=['GET', 'POST'])
|
@conversations_bp.route('/create', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify
|
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify
|
||||||
from flask_login import login_required, current_user
|
from flask_login import login_required, current_user
|
||||||
from models import db, Room, User, RoomMemberPermission, RoomFile, Notif
|
from models import db, Room, User, RoomMemberPermission, RoomFile, Notif, DocuPulseSettings
|
||||||
from forms import RoomForm
|
from forms import RoomForm
|
||||||
from routes.room_files import user_has_permission
|
from routes.room_files import user_has_permission
|
||||||
from routes.auth import require_password_change
|
from routes.auth import require_password_change
|
||||||
@@ -36,7 +36,11 @@ def rooms():
|
|||||||
if search:
|
if search:
|
||||||
query = query.filter(Room.name.ilike(f'%{search}%'))
|
query = query.filter(Room.name.ilike(f'%{search}%'))
|
||||||
rooms = query.order_by(Room.created_at.desc()).all()
|
rooms = query.order_by(Room.created_at.desc()).all()
|
||||||
return render_template('rooms/rooms.html', rooms=rooms, search=search)
|
|
||||||
|
# Get usage stats
|
||||||
|
usage_stats = DocuPulseSettings.get_usage_stats()
|
||||||
|
|
||||||
|
return render_template('rooms/rooms.html', rooms=rooms, search=search, usage_stats=usage_stats)
|
||||||
|
|
||||||
@rooms_bp.route('/create', methods=['GET', 'POST'])
|
@rooms_bp.route('/create', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
|
|||||||
@@ -8,11 +8,39 @@
|
|||||||
title="Conversations",
|
title="Conversations",
|
||||||
description="Manage your conversations and messages",
|
description="Manage your conversations and messages",
|
||||||
button_text="New Conversation" if current_user.is_admin or current_user.is_manager else "",
|
button_text="New Conversation" if current_user.is_admin or current_user.is_manager else "",
|
||||||
button_url=url_for('conversations.create_conversation') if current_user.is_admin or current_user.is_manager else "",
|
button_url="#" if current_user.is_admin or current_user.is_manager else "",
|
||||||
icon="fa-comments",
|
icon="fa-comments",
|
||||||
button_icon="fa-plus"
|
button_icon="fa-plus"
|
||||||
) }}
|
) }}
|
||||||
|
|
||||||
|
<!-- Conversation Limit Modal -->
|
||||||
|
<div class="modal fade" id="conversationLimitModal" tabindex="-1" aria-labelledby="conversationLimitModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="conversationLimitModalLabel">Conversation Limit Reached</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="d-flex align-items-center gap-3 mb-3">
|
||||||
|
<i class="fas fa-exclamation-circle text-warning" style="font-size: 2rem;"></i>
|
||||||
|
<div>
|
||||||
|
<h6 class="mb-1">Maximum Conversations Reached</h6>
|
||||||
|
<p class="text-muted mb-0">You have reached the maximum number of conversations allowed ({{ usage_stats.max_conversations }}).</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="alert alert-info">
|
||||||
|
<i class="fas fa-info-circle me-2"></i>
|
||||||
|
Please contact your administrator if you need to create more conversations.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">OK</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="container mt-4">
|
<div class="container mt-4">
|
||||||
<!-- Search and Filter Section -->
|
<!-- Search and Filter Section -->
|
||||||
<div class="bg-white rounded-lg shadow-sm p-4 mb-4">
|
<div class="bg-white rounded-lg shadow-sm p-4 mb-4">
|
||||||
@@ -123,5 +151,34 @@
|
|||||||
|
|
||||||
{% block extra_js %}
|
{% block extra_js %}
|
||||||
<script src="{{ url_for('static', filename='js/conversations-list.js') }}?v={{ 'js/conversations-list.js'|asset_version }}"></script>
|
<script src="{{ url_for('static', filename='js/conversations-list.js') }}?v={{ 'js/conversations-list.js'|asset_version }}"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Get the New Conversation button and add click handler
|
||||||
|
const newConversationBtn = document.querySelector('header button');
|
||||||
|
if (newConversationBtn) {
|
||||||
|
newConversationBtn.addEventListener('click', function(e) {
|
||||||
|
if ({{ usage_stats.current_conversations }} >= {{ usage_stats.max_conversations }}) {
|
||||||
|
e.preventDefault();
|
||||||
|
var conversationLimitModal = new bootstrap.Modal(document.getElementById('conversationLimitModal'));
|
||||||
|
conversationLimitModal.show();
|
||||||
|
} else {
|
||||||
|
window.location.href = '{{ url_for("conversations.create_conversation") }}';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle modal backdrop removal
|
||||||
|
const conversationLimitModal = document.getElementById('conversationLimitModal');
|
||||||
|
if (conversationLimitModal) {
|
||||||
|
conversationLimitModal.addEventListener('hidden.bs.modal', function () {
|
||||||
|
document.body.classList.remove('modal-open');
|
||||||
|
const backdrop = document.querySelector('.modal-backdrop');
|
||||||
|
if (backdrop) {
|
||||||
|
backdrop.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{% extends "common/base.html" %}
|
{% extends "common/base.html" %}
|
||||||
{% from "components/header.html" import header %}
|
{% from "components/header.html" import header %}
|
||||||
|
|
||||||
{% block title %}Rooms - DocuPulse{% endblock %}
|
{% block title %}Rooms - {% if site_settings.company_name %}DocuPulse for {{ site_settings.company_name }}{% else %}DocuPulse{% endif %}{% endblock %}
|
||||||
|
|
||||||
{% block extra_css %}
|
{% block extra_css %}
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/rooms.css') }}?v={{ 'css/rooms.css'|asset_version }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/rooms.css') }}?v={{ 'css/rooms.css'|asset_version }}">
|
||||||
@@ -10,13 +10,11 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
{{ header(
|
{{ header(
|
||||||
title="Rooms",
|
title="Rooms",
|
||||||
description="Manage your document rooms and collaborate with team members",
|
description="Manage your rooms and documents",
|
||||||
button_text="New Room",
|
button_text="New Room",
|
||||||
button_url=url_for('rooms.create_room'),
|
button_url="#",
|
||||||
icon="fa-door-open",
|
icon="fa-door-open",
|
||||||
button_icon="fa-plus",
|
button_icon="fa-plus"
|
||||||
button_class="btn-primary",
|
|
||||||
button_style="padding: 0.4rem 1rem;"
|
|
||||||
) }}
|
) }}
|
||||||
|
|
||||||
<div class="container mt-4">
|
<div class="container mt-4">
|
||||||
@@ -99,21 +97,11 @@
|
|||||||
<div class="modal-dialog modal-dialog-centered">
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="deleteRoomModalLabel{{ room.id }}">Move to Trash</h5>
|
<h5 class="modal-title" id="deleteRoomModalLabel{{ room.id }}">Delete Room</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="d-flex align-items-center gap-3 mb-3">
|
<p>Are you sure you want to delete the room "{{ room.name }}"? This action cannot be undone.</p>
|
||||||
<i class="fas fa-trash text-danger" style="font-size: 2rem;"></i>
|
|
||||||
<div>
|
|
||||||
<h6 class="mb-1">Move to Trash</h6>
|
|
||||||
<p class="text-muted mb-0" id="deleteFileName{{ room.id }}">{{ room.name }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="alert alert-warning">
|
|
||||||
<i class="fas fa-exclamation-triangle text-warning"></i>
|
|
||||||
This Room will be permanently deleted. This action cannot be undone. Are you sure you want to proceed?
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||||
@@ -132,7 +120,64 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Room Limit Modal -->
|
||||||
|
<div class="modal fade" id="roomLimitModal" tabindex="-1" aria-labelledby="roomLimitModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="roomLimitModalLabel">Room Limit Reached</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="d-flex align-items-center gap-3 mb-3">
|
||||||
|
<i class="fas fa-exclamation-circle text-warning" style="font-size: 2rem;"></i>
|
||||||
|
<div>
|
||||||
|
<h6 class="mb-1">Maximum Rooms Reached</h6>
|
||||||
|
<p class="text-muted mb-0">You have reached the maximum number of rooms allowed ({{ usage_stats.max_rooms }}).</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="alert alert-info">
|
||||||
|
<i class="fas fa-info-circle me-2"></i>
|
||||||
|
Please contact your administrator if you need to create more rooms.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">OK</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{% block extra_js %}
|
{% block extra_js %}
|
||||||
<script src="{{ url_for('static', filename='js/rooms-list.js') }}?v={{ 'js/rooms-list.js'|asset_version }}"></script>
|
<script src="{{ url_for('static', filename='js/rooms-list.js') }}?v={{ 'js/rooms-list.js'|asset_version }}"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
// Get the New Room button and add click handler
|
||||||
|
const newRoomBtn = document.querySelector('header button');
|
||||||
|
if (newRoomBtn) {
|
||||||
|
newRoomBtn.addEventListener('click', function(e) {
|
||||||
|
if ({{ usage_stats.current_rooms }} >= {{ usage_stats.max_rooms }}) {
|
||||||
|
e.preventDefault();
|
||||||
|
var roomLimitModal = new bootstrap.Modal(document.getElementById('roomLimitModal'));
|
||||||
|
roomLimitModal.show();
|
||||||
|
} else {
|
||||||
|
window.location.href = '{{ url_for("rooms.create_room") }}';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle modal backdrop removal
|
||||||
|
const roomLimitModal = document.getElementById('roomLimitModal');
|
||||||
|
if (roomLimitModal) {
|
||||||
|
roomLimitModal.addEventListener('hidden.bs.modal', function () {
|
||||||
|
document.body.classList.remove('modal-open');
|
||||||
|
const backdrop = document.querySelector('.modal-backdrop');
|
||||||
|
if (backdrop) {
|
||||||
|
backdrop.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user