miguelgrinberg / microblog

The microblogging application developed in my Flask Mega-Tutorial series. This version maps to the 2024 Edition of the tutorial.
http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world
MIT License
4.52k stars 1.62k forks source link

bootstrap,jinjia html template for user profile based on flask #89

Closed tianke0711 closed 5 years ago

tianke0711 commented 6 years ago

Now I am developing a web page for me to manage my profile and blog information like the image as following:

screen shot 2018-02-26 at 18 44 06

I can do the base.html for navigation bar. when I click the profile to the profile web pages for managing blogs, comments, users when click the related options(blogs, comments). I want to when I click the options, the profile below the navigation bar is left, and just change the read rectangle part which I want to show information for each option. Are there some bootstrap,jinjia html template templates for it or how to realize it. Do you guys @miguelgrinberg have some advices.

miguelgrinberg commented 6 years ago

Yes, you can use Tabs. See https://getbootstrap.com/docs/3.3/components/#nav-tabs.

tianke0711 commented 6 years ago

thanks @miguelgrinberg , I will try it and report it.

tianke0711 commented 6 years ago

Hi @miguelgrinberg thanks for your advice. Now I have used tab as you suggested. The image is as following. But Now I want when I click the options, the profile below the navigation bar and profile information part (green) are remained, and just change the read rectangle part which I want to show information for each option.

screen shot 2018-02-27 at 10 46 00

Now I am design base html base_profile.html like base.html as following, the option html(such as blogs, comments, et al.,) to extend the html, but when I click the comment. the profile information part is disappeared. There may be something is wrong or how to design the base_profile.html

:

`{% extends 'bootstrap/base.html' %}

{% block title %}
    {% if title %}{{ title }} - Microblog{% else %}{{ _('Welcome to Microblog') }}{% endif %}
{% endblock %}

{% block styles %}
    {{super()}}
    <link rel="stylesheet" href="{{url_for('static', filename='css/custom.css')}}">
    <link rel="stylesheet" href="{{url_for('static', filename='css/font-awesome.min.css')}}">

{% endblock %}

{% block navbar %}
    <nav class="navbar navbar-default navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="{{ url_for('main.index') }}">SciSci</a>
            </div>
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav">
                    <li><a href="{{ url_for('main.index') }}">{{ _('Home') }}</a></li>
                    <li><a href="{{ url_for('main.explore') }}">{{ _('Blog') }}</a></li>
                </ul>
                {% if g.search_form %}
                <form class="navbar-form navbar-left" method="get" action="{{ url_for('main.search') }}">
                    <div class="form-group">
                        {{ g.search_form.q(size=20, class='form-control', placeholder=g.search_form.q.label.text) }}
                    </div>
                </form>
                {% endif %}
                <ul class="nav navbar-nav navbar-right">
                    {% if current_user.is_anonymous %}

                    <li><a href="{{ url_for('auth.login') }}">{{ _('Sign In') }}</a></li>
                    <li><a href="{{ url_for('auth.register') }}">{{ _('Sign Up') }}</a></li>
                    {% else %}
                    {% if current_user.admin %}
                    <li><a href="{{ url_for('main.create_blog') }}">{{ _('Create Blog') }}</a></li>
                    {% endif %}
                    <li>
                        <a href="{{ url_for('main.messages') }}">{{ _('Messages') }}
                            {% set new_messages = current_user.new_messages() %}
                            <span id="message_count" class="badge"
                                  style="visibility: {% if new_messages %}visible
                                                     {% else %}hidden{% endif %};">
                                {{ new_messages }}
                            </span>
                        </a>
                    </li>
                    <li><a href="{{ url_for('main.user', username=current_user.username) }}">{{ _('Profile') }}</a></li>
                    <li><a href="{{ url_for('auth.logout') }}">{{ _('Sign Out') }}</a></li>

                    {% endif %}
                </ul>
            </div>
        </div>
    </nav>

{% endblock %}

{% block content %}
    <div class="container">
        {% if current_user.is_authenticated %}
        {% with tasks = current_user.get_tasks_in_progress() %}
        {% if tasks %}
            {% for task in tasks %}
            <div class="alert alert-success" role="alert">
                {{ task.description }}
                <span id="{{ task.id }}-progress">{{ task.get_progress() }}</span>%
            </div>
            {% endfor %}
        {% endif %}
        {% endwith %}
        {% endif %}
        {% with messages = get_flashed_messages() %}
        {% if messages %}
            {% for message in messages %}
            <div class="alert alert-info" role="alert">{{ message }}</div>
            {% endfor %}
        {% endif %}
        {% endwith %}

        {% block app_content %}
        {% import "_macros.html" as macros %}
        <div class="panel panel-default"  >
        <div class="userProfileSection1">
            <img src="{{ user.avatar(58) }}" >
        </div>
        <div class="userProfileSection2">

            <div id="userName" >
                <h3 style="display:inline">{{ user.username }}</h3>

                {% if user==current_user and current_user.admin !=1 %}

                <a class="btn btn-default btn-sm" href='{{url_for("main.edit_profile")}}' style="margin-bottom: 10px;margin-left: 10px;"><span class="glyphicon glyphicon-pencil"></span>
                    Edit</a>

                {% endif %}
                {% if current_user.admin %}
                <a class="btn btn-danger btn-sm" style="margin-bottom: 10px;margin-left: 10px;" href="{{ url_for('main.edit_profile') }}">{{ _('Edit your profile') }}</a>
                {% endif %}

                {% if user != current_user %}
                    {% if not current_user.is_following(user) %}
                    <a href="{{ url_for('main.follow', username=user.username) }}" class="btn follow">Follow</a>
                    {% else %}
                    <a href="{{ url_for('main.unfollow', username=user.username) }}" class="btn unfollow">Following</a>
                    {% endif %}
                {% endif %}

            </div>

            <div id="userInfoOthers" >
                {% if user.name %}
                    <p>
                        {% if user.name %}{{ user.name }}{% endif %}
                    </p>
                {% endif %}
                {% if current_user.admin %}
                    <p><a href="mailto:{{ user.email }}">{{ user.email }}</a></p>
                {% endif %}
                {% if user.about_me %}<p>{{ user.about_me }}</p>{% endif %}
                <p>
                    Last seen {{ moment(user.last_seen).fromNow() }}.
                </p>
            </div>
            <div class="socials tex-center"> <a href="" class="btn btn-circle btn-primary ">
                    <i class="fa fa-facebook"></i></a> <a href="" class="btn btn-circle btn-danger ">
                    <i class="fa fa-google-plus"></i></a> <a href="" class="btn btn-circle btn-info ">
                    <i class="fa fa-twitter"></i></a> <a href="" class="btn btn-circle btn-warning ">
                    <i class="fa fa-envelope"></i></a>
            </div>
        </div>

        <div class="userProfileSection3">

                <ul class="nav nav-pills pull-left countlist" role="tablist">
                    <li role="presentation">
                    <h3><a href="{{ url_for('main.followers', username=user.username) }}">{{ user.followers.count() }}</a><br>
                        <small>Follower</small> </h3>
                    </li>
                    <li role="presentation">
                    <h3><a href="{{ url_for('main.followed_by', username=user.username) }}">{{ user.followed.count() }}</a><br>
                        <small>Following</small> </h3>
                    </li>

                </ul>
        </div>
        <div class="clearfix" style="clear:both"></div>

</div>

    <ul class="nav nav-tabs">
            {% if current_user.admin %}
                <li role="presentation" class="active"><a href="{{ url_for('main.manage_posts', username=current_user.username) }}">Blogs</a></li>
                <li role="presentation"><a href="{{ url_for('main.moderate_comments') }}">Comments</a></li>
                <li role="presentation"><a href="{{ url_for('main.explore') }}">Users</a></li>
                <li role="presentation"><a href="{{ url_for('main.index') }}">Questions</a></li>
                <li role="presentation"><a href="{{ url_for('main.index') }}">Answers</a></li>

            {% else %}
                <li class="active"><a href="{{ url_for('main.index') }}">Questions</a></li>
                <li class="active"><a href="{{ url_for('main.index') }}">Answers</a></li>
            {% endif %}

    </ul>
        {% endblock %}

    </div>

{% endblock %}

{% block scripts %}
    {{ super() }}
    {{ moment.include_moment(local_js="/static/js/moment-with-locales.min.js") }}
    {{ moment.lang(g.locale) }}
    <script>
        function translate(sourceElem, destElem, sourceLang, destLang) {
            $(destElem).html('<img src="{{ url_for('static', filename='loading.gif') }}">');
            $.post('/translate', {
                text: $(sourceElem).text(),
                source_language: sourceLang,
                dest_language: destLang
            }).done(function(response) {
                $(destElem).text(response['text'])
            }).fail(function() {
                $(destElem).text("{{ _('Error: Could not contact server.') }}");
            });
        }
        $(function () {
            var timer = null;
            var xhr = null;
            $('.user_popup').hover(
                function(event) {
                    // mouse in event handler
                    var elem = $(event.currentTarget);
                    timer = setTimeout(function() {
                        timer = null;
                        xhr = $.ajax(
                            '/user/' + elem.first().text().trim() + '/popup').done(
                                function(data) {
                                    xhr = null;
                                    elem.popover({
                                        trigger: 'manual',
                                        html: true,
                                        animation: false,
                                        container: elem,
                                        content: data
                                    }).popover('show');
                                    flask_moment_render_all();
                                }
                            );
                    }, 1000);
                },
                function(event) {
                    // mouse out event handler
                    var elem = $(event.currentTarget);
                    if (timer) {
                        clearTimeout(timer);
                        timer = null;
                    }
                    else if (xhr) {
                        xhr.abort();
                        xhr = null;
                    }
                    else {
                        elem.popover('destroy');
                    }
                }
            );
        });
        function set_message_count(n) {
            $('#message_count').text(n);
            $('#message_count').css('visibility', n ? 'visible' : 'hidden');
        }
        function set_task_progress(task_id, progress) {
            $('#' + task_id + '-progress').text(progress);
        }
        {% if current_user.is_authenticated %}
        $(function() {
            var since = 0;
            setInterval(function() {
                $.ajax('{{ url_for('main.notifications') }}?since=' + since).done(
                    function(notifications) {
                        for (var i = 0; i < notifications.length; i++) {
                            switch (notifications[i].name) {
                                case 'unread_message_count':
                                    set_message_count(notifications[i].data);
                                    break;
                                case 'task_progress':
                                    set_task_progress(notifications[i].data.task_id,
                                        notifications[i].data.progress);
                                    break;
                            }
                            since = notifications[i].timestamp;
                        }
                    }
                );
            }, 10000);
        });
        {% endif %}
    </script>
{% endblock %}
`

model.py about moderate_comments

@bp.route("/manage_comments", methods=["GET","POST"])
@login_required
def moderate_comments():
    page = request.args.get('page', 1, type=int)
    pagination = Comment.query.order_by(Comment.timestamp.desc()).paginate(page, per_page=current_app.config['FLASKY_POSTS_PER_PAGE'], error_out=False)
    comments = pagination.items
    return render_template('comments.html', pagination=pagination,comments=comments)

the comments. html

{% extends "base_profile.html" %}
{% import "_macros.html" as macros with context %}
{% block title %}Flasky - Post{% endblock %}
{% block app_content %}
    {% set moderate = True %}
    {% include '_comments.html' %}
    {% if pagination %}
        <div class="comment-pagination" >
            {{ macros.pagination_widget(pagination, 'main.moderate_comments') }}
        </div>
        <div class="clear" style="clear:both"></div>
    {% endif %}

{% endblock %}
tianke0711 commented 6 years ago

hi @miguelgrinberg do you have advice about this issue, If possible.

miguelgrinberg commented 6 years ago

The bootstrap docs have examples of how to do this. Have you seen them?

miguelgrinberg commented 5 years ago

This issue will be automatically closed due to being inactive for more than six months. Please reopen if you need more assistance.