Update url pathname without using dcc.Link (just callback)

UPDATE: I DIT IT (SEE NEXT COMMENT)

I have the app tree structsure using pages, like the following:

main.py
pages
  |
   ------login.py
  |
   ------analitics.py (simulated as html.Div("LOGADO") inside first calback at main.py)

I want to reset de url pathname to initial name after the time ending (like a session time), but the url keeps the same (http://127.0.0.1:8050/analitics)

  1. the app starts at the login page (http://127.0.0.1:8050/)
  2. input the login and password (any login and password can be used, just for tests)
  3. the dcc.Interval start to count
  4. the analitics.py is opened and the url changes to http://127.0.0.1:8050/analitics
  5. the times expires and the layout is back to login page but the url keeps http://127.0.0.1:8050/analitics

I want to in the 5th step the url resets to http://127.0.0.1:8050/ instead keeping at http://127.0.0.1:8050/analitics

the code is:

main.py

from dash import Dash, register_page, dcc, html, Input, Output, ctx
from dash.exceptions import PreventUpdate
from pages import login, labelsAnalisys
##from threading import Timer
##from time import time


##external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = Dash(
    __name__,
    use_pages=True,
)#, external_stylesheets=external_stylesheets)


app.layout = html.Div(

    children = [

        dcc.Location(id='url', refresh=False),

        login.layout

    ],

    id="main-container"
)



@app.callback(
    Output("main-container", 'children'),
    Output("url", "pathname"),
    Input('user-input', 'value'),
    Input('password-input', 'value'),
    Input('login-button', 'n_clicks'),
)
def login_state(input_user_input, input_password_input, login_button):

    if (input_user_input != None) and (input_password_input != None) and (ctx.triggered_id == "login-button"):

        return(
            html.Div(
                children=[
                    dcc.Location(id='url', refresh=False),
                    html.Div(
                        children=[f"LOGADO COM SUCESSO"],
                        id='login-message-label',
                        style={"text-align":"center"}
                    ),
                    html.Div("LOGADO"),
                    dcc.Interval(
                        id='interval-component',
                        interval=1000, # update every 1000 milliseconds (1 second)
                        n_intervals=0
                    )
                ],

                id="main-container-1"

            ),

            "analitics"

        )

    else:

        raise PreventUpdate



@app.callback(
    Output('login-message-label', 'children'),
    Input("interval-component", 'n_intervals')
)
def login_session_time(n):
    return(
        f"LOGADO COM SUCESSO HÁ {n} SEGUNDOS"
    )


@app.callback(
    Output('main-container-1', 'children'),
    Input("interval-component", 'n_intervals')
)
def back_login_page(n):
    if n == 5:
        return(
            login.layout
        )
    else:
        raise PreventUpdate


if __name__ == '__main__':

    app.run_server(debug=True)


pages/login.py

from dash import dcc, html


layout = html.Div(

    children=[

        html.Div(
            children=[f"Usuário"],
            id='user-input-label',
            style={"text-align":"center"}
        ),

        dcc.Input(
            placeholder="Insira o usuário",
            id='user-input',
            type="text",
            style={
                "text-align":"center",
                "display": "block",
                "margin":"auto",
            }
        ),

        html.Br(),

        html.Div(
            children=["Senha"],
            id='password-input-label',
            style={"text-align":"center"}
        ),

        dcc.Input(
            placeholder="Insira a senha",
            id='password-input',
            type="password",
            style={
                "text-align":"center",
                "display": "block",
                "margin":"auto",

            }

        ),

        html.Br(),

        html.Button(
            "login",
            id="login-button",
            style={
                "text-align":"center",
                "display": "block",
                "margin":"auto",

            }
        )

    ],

    id="login-page-container"

)

I tried some tutorials, but I’m stuck with the output limitation at one callback and I don’t want to depend on dcc.Link() to change the url path

SOLUTION:

I have updated to new dash 2.9.2 (this version now allows using same output in multiple callbacks see :mega: Dash 2.9.2 Released - Partial Property Updates with Patch(), Duplicate Outputs, dcc.Geolocation, Scatter Group Attributes and More - Dash Python - Plotly Community Forum), so the main page became:

from dash import Dash, register_page, dcc, html, Input, Output, ctx
from dash.exceptions import PreventUpdate
from pages import login, labelsAnalisys
##from threading import Timer
##from time import time


##external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = Dash(
    __name__,
    use_pages=True,
##    prevent_initial_callback="initial_duplicate", # é necessário para multiplos outputs
)#, external_stylesheets=external_stylesheets)


app.layout = html.Div(

    children = [

        dcc.Location(id='url', refresh=False),

        login.layout

    ],

    id="main-container"
)



@app.callback(
    Output("main-container", 'children'),
    Output("url", "pathname", allow_duplicate=True),
    Input('user-input', 'value'),
    Input('password-input', 'value'),
    Input('login-button', 'n_clicks'),
    prevent_initial_call=True,
)
def login_state(input_user_input, input_password_input, login_button):

    if (input_user_input != None) and (input_password_input != None) and (ctx.triggered_id == "login-button"):

        return(
            html.Div(
                children=[
                    dcc.Location(id='url', refresh=False),
                    html.Div(
                        children=[f"LOGADO COM SUCESSO"],
                        id='login-message-label',
                        style={"text-align":"center"}
                    ),
                    html.Div("LOGADO"),
                    dcc.Interval(
                        id='interval-component',
                        interval=1000, # update every 1000 milliseconds (1 second)
                        n_intervals=0
                    )
                ],

                id="main-container-1"

            ),

            "analitics"

        )

    else:

        raise PreventUpdate



@app.callback(
    Output('login-message-label', 'children'),
    Input("interval-component", 'n_intervals')
)
def login_session_time(n):
    return(
        f"LOGADO COM SUCESSO HÁ {n} SEGUNDOS"
    )


@app.callback(
    Output('main-container-1', 'children'),
    Output("url", "pathname"),
    Input("interval-component", 'n_intervals')
)
def back_login_page(n):
    if n == 5:
        return(
            login.layout, "/"
        )
    else:
        raise PreventUpdate


if __name__ == '__main__':

    app.run_server(debug=True)