Views
The panel's screens are Propel views in the ignite namespace. The app can add its own pages in resources/views/, and they can extend the panel's layout.
The ignite namespace
Ignite::new() registers the ignite namespace. The views in it are:
ignite::layouts.app, the page frame, with the header and navigation.ignite::login, the sign-in page.ignite::dashboard, the stat cards and the latest records.ignite::index, the list of a resource.ignite::form, the create and edit pages.ignite::partials.flash, the message shown after a change.
Extend the layout
A view of the app extends the panel's layout and fills its title and content sections. It needs only its own variables. This view shows the signed-in user, and the route in Panel renders it with user_id:
@extends('ignite::layouts.app')
@section('title')
Account
@endsection
@section('content')
<h1>Account</h1>
<p>Signed in as user {{ $user_id }}.</p>
@endsection
The view is resources/views/account.propel, and the view name is account.
The layout also yields three sections for the panel's own chrome. The panel's pages set them, and an app view can set them too:
ignite_home, the brand link in the header. It defaults to/admin.ignite_nav, the navigation and the sign-out button. It is empty by default, so an app view has no navigation unless it sets this section.ignite_flash, the message shown after a change. It is empty by default.
An app cannot replace one of the panel's views on its own. The only way to change a panel view is to point the panel at a directory, which replaces all of them.
Where the views come from
A debug build renders the panel's views with Propel's dev renderer, which reads them on each request. A release build renders compiled views only: the panel's build script compiles the four panel views, the dashboard, the form, the index and the login, into Rust. Both builds embed the views in the ignite-panel binary, so the default needs no view files.
In a debug build, Ignite::views_dir does this in the builder, and the IGNITE_VIEWS_DIR environment variable does the same from the environment. The builder call wins over the variable. The directory makes the dev renderer read the views from disk, so a developer can edit them without rebuilding. It replaces all of the panel's views, and it must contain layouts/app.propel. fairing() panics when that file is missing. A release build ignores both.
use ignite_panel::Ignite;
/// The panel with its views read from a directory on disk, so the views can be
/// edited without rebuilding. Without this call, the views are embedded.
pub fn panel() -> Ignite {
Ignite::new().views_dir("/srv/ignite/views")
}
An app that renders its own views in release compiles them with its own build.rs, as the panel does, and its page contexts are plain structs. The app's views can extend the panel's layout, ignite::layouts.app. The panel publishes its views directory to the apps that depend on it, through the links key in its manifest, so the app's build script finds it in DEP_IGNITE_PANEL_VIEWS_DIR and compiles the panel's layout with the app's views. The app needs propel_compiler as a build dependency at the same Propel pin. The contract describes this rule in its Views section, and the example app's build script does this:
//! Compiles the app's views into Rust, so a release build renders them without a
//! template interpreter. The panel's own views are compiled too, because the
//! app's views extend its layout (`ignite::layouts.app`).
fn main() {
// ignite-panel publishes its views directory to its dependents.
let panel_views = std::env::var("DEP_IGNITE_PANEL_VIEWS_DIR")
.expect("ignite-panel publishes its views directory");
propel_compiler::build::Views::new("resources/views")
.namespace("ignite", panel_views)
.asset_namespace("ui")
.view("home", "crate::Home")
.view("subscribe", "crate::subscribe::Subscribe")
.build();
}
The panel registers its own stylesheet and script, the ui asset namespace, so an app needs no asset step: not in a page helper, not in a view's context. A view that extends the layout is compiled into the app's build, and the layout names ui::, so the app's build script declares the namespace with .asset_namespace("ui"), as the example's build script does. The build fails without that line.
Ignite