initial work of the arcline tickets
This commit is contained in:
31
templates/base.html
Normal file
31
templates/base.html
Normal file
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}Arcline Tickets{% endblock %}</title>
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<div class="container">
|
||||
<a href="{{ url_for('index') }}" class="logo">Arcline <span class="accent">Tickets</span></a>
|
||||
<nav>
|
||||
<a href="{{ url_for('index') }}">All Tickets</a>
|
||||
<a href="{{ url_for('create_ticket') }}" class="btn btn-primary btn-sm">+ New Ticket</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container">
|
||||
{% block content %}{% endblock %}
|
||||
</main>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="container">
|
||||
<p>Arcline Tickets — Built with Python, Flask & Jinja2</p>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
73
templates/create.html
Normal file
73
templates/create.html
Normal file
@@ -0,0 +1,73 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}New Ticket{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="page-header">
|
||||
<h1>Create New Ticket</h1>
|
||||
</div>
|
||||
|
||||
<div class="form-container">
|
||||
{% if error %}
|
||||
<div class="alert alert-error">{{ error }}</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" class="ticket-form">
|
||||
<div class="form-group">
|
||||
<label for="title">Title <span class="required">*</span></label>
|
||||
<input type="text" id="title" name="title" class="input"
|
||||
value="{{ ticket.title if ticket else '' }}" required autofocus
|
||||
placeholder="Brief summary of the issue">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Description</label>
|
||||
<textarea id="description" name="description" class="input" rows="6"
|
||||
placeholder="Detailed description of the issue...">{{ ticket.description if ticket else '' }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="priority">Priority</label>
|
||||
<select id="priority" name="priority" class="input">
|
||||
{% for val, label in priorities %}
|
||||
<option value="{{ val }}" {% if ticket and ticket.priority.value == val %}selected{% endif %}>
|
||||
{{ label }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="status">Status</label>
|
||||
<select id="status" name="status" class="input">
|
||||
{% for val, label in statuses %}
|
||||
<option value="{{ val }}" {% if ticket and ticket.status.value == val %}selected{% elif val == 'open' %}selected{% endif %}>
|
||||
{{ label }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="assignee">Assignee</label>
|
||||
<input type="text" id="assignee" name="assignee" class="input"
|
||||
value="{{ ticket.assignee if ticket else '' }}"
|
||||
placeholder="Who is responsible?">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="project">Project / Tool</label>
|
||||
<input type="text" id="project" name="project" class="input"
|
||||
value="{{ ticket.project if ticket else '' }}"
|
||||
placeholder="e.g. CLI, Web, API">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<a href="{{ url_for('index') }}" class="btn btn-ghost">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary">Create Ticket</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
66
templates/detail.html
Normal file
66
templates/detail.html
Normal file
@@ -0,0 +1,66 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Ticket #{{ ticket.id }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<a href="{{ url_for('index') }}" class="back-link">← Back to tickets</a>
|
||||
<h1>#{{ ticket.id }} — {{ ticket.title }}</h1>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a href="{{ url_for('edit_ticket', ticket_id=ticket.id) }}" class="btn btn-secondary">Edit</a>
|
||||
<form method="post" action="{{ url_for('delete_ticket', ticket_id=ticket.id) }}"
|
||||
onsubmit="return confirm('Delete this ticket?');" style="display:inline;">
|
||||
<button type="submit" class="btn btn-danger">Delete</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ticket-detail-grid">
|
||||
<div class="ticket-main">
|
||||
<div class="ticket-section">
|
||||
<h3>Description</h3>
|
||||
<div class="ticket-description">
|
||||
{% if ticket.description %}
|
||||
<p>{{ ticket.description }}</p>
|
||||
{% else %}
|
||||
<p class="muted">No description provided.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside class="ticket-sidebar">
|
||||
<div class="ticket-meta-card">
|
||||
<div class="meta-row">
|
||||
<span class="meta-label">Status</span>
|
||||
<span class="badge badge-{{ ticket.status.value }}">{{ ticket.status.value.replace('_', ' ') | title }}</span>
|
||||
</div>
|
||||
<div class="meta-row">
|
||||
<span class="meta-label">Priority</span>
|
||||
<span class="badge badge-priority badge-p-{{ ticket.priority.value }}">{{ ticket.priority.value | upper }}</span>
|
||||
</div>
|
||||
<div class="meta-row">
|
||||
<span class="meta-label">Assignee</span>
|
||||
<span>{% if ticket.assignee %}{{ ticket.assignee }}{% else %}<span class="muted">Unassigned</span>{% endif %}</span>
|
||||
</div>
|
||||
{% if ticket.project %}
|
||||
<div class="meta-row">
|
||||
<span class="meta-label">Project</span>
|
||||
<span class="badge badge-project">{{ ticket.project }}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
<hr>
|
||||
<div class="meta-row">
|
||||
<span class="meta-label">Created</span>
|
||||
<span class="date">{{ ticket.created_at[:19] }}</span>
|
||||
</div>
|
||||
<div class="meta-row">
|
||||
<span class="meta-label">Updated</span>
|
||||
<span class="date">{{ ticket.updated_at[:19] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
73
templates/edit.html
Normal file
73
templates/edit.html
Normal file
@@ -0,0 +1,73 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Edit Ticket #{{ ticket.id }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="page-header">
|
||||
<h1>Edit Ticket #{{ ticket.id }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="form-container">
|
||||
{% if error %}
|
||||
<div class="alert alert-error">{{ error }}</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" class="ticket-form">
|
||||
<div class="form-group">
|
||||
<label for="title">Title <span class="required">*</span></label>
|
||||
<input type="text" id="title" name="title" class="input"
|
||||
value="{{ ticket.title }}" required autofocus
|
||||
placeholder="Brief summary of the issue">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="description">Description</label>
|
||||
<textarea id="description" name="description" class="input" rows="6"
|
||||
placeholder="Detailed description of the issue...">{{ ticket.description }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="priority">Priority</label>
|
||||
<select id="priority" name="priority" class="input">
|
||||
{% for val, label in priorities %}
|
||||
<option value="{{ val }}" {% if ticket.priority.value == val %}selected{% endif %}>
|
||||
{{ label }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="status">Status</label>
|
||||
<select id="status" name="status" class="input">
|
||||
{% for val, label in statuses %}
|
||||
<option value="{{ val }}" {% if ticket.status.value == val %}selected{% endif %}>
|
||||
{{ label }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="assignee">Assignee</label>
|
||||
<input type="text" id="assignee" name="assignee" class="input"
|
||||
value="{{ ticket.assignee }}"
|
||||
placeholder="Who is responsible?">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="project">Project / Tool</label>
|
||||
<input type="text" id="project" name="project" class="input"
|
||||
value="{{ ticket.project }}"
|
||||
placeholder="e.g. CLI, Web, API">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<a href="{{ url_for('view_ticket', ticket_id=ticket.id) }}" class="btn btn-ghost">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary">Save Changes</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
80
templates/index.html
Normal file
80
templates/index.html
Normal file
@@ -0,0 +1,80 @@
|
||||
{% extends "base.html" %}
|
||||
{% block title %}Tickets{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="page-header">
|
||||
<h1>Tickets</h1>
|
||||
<a href="{{ url_for('create_ticket') }}" class="btn btn-primary">+ New Ticket</a>
|
||||
</div>
|
||||
|
||||
{# ── stats bar ── #}
|
||||
<div class="stats-bar">
|
||||
<a href="{{ url_for('index') }}" class="stat {% if not status_filter %}active{% endif %}">
|
||||
<span class="stat-num">{{ tickets|length }}</span>
|
||||
<span class="stat-label">Total</span>
|
||||
</a>
|
||||
{% for val, label in statuses %}
|
||||
<a href="{{ url_for('index', status=val, priority=priority_filter, search=search, project=project_filter) }}"
|
||||
class="stat stat-{{ val }} {% if status_filter == val %}active{% endif %}">
|
||||
<span class="stat-num">{{ counts.get(val, 0) }}</span>
|
||||
<span class="stat-label">{{ label }}</span>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{# ── filters ── #}
|
||||
<form method="get" class="filters">
|
||||
<input type="text" name="search" placeholder="Search tickets..." value="{{ search }}"
|
||||
class="input search-input">
|
||||
<select name="priority" class="input">
|
||||
<option value="">All Priorities</option>
|
||||
{% for val, label in priorities %}
|
||||
<option value="{{ val }}" {% if priority_filter == val %}selected{% endif %}>{{ label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% if projects %}
|
||||
<select name="project" class="input">
|
||||
<option value="">All Projects</option>
|
||||
{% for p in projects %}
|
||||
<option value="{{ p }}" {% if project_filter == p %}selected{% endif %}>{{ p }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{% endif %}
|
||||
<button type="submit" class="btn btn-secondary">Filter</button>
|
||||
{% if status_filter or priority_filter or search or project_filter %}
|
||||
<a href="{{ url_for('index') }}" class="btn btn-ghost">Clear</a>
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
{# ── ticket list ── #}
|
||||
{% if tickets %}
|
||||
<div class="ticket-list">
|
||||
{% for ticket in tickets %}
|
||||
<a href="{{ url_for('view_ticket', ticket_id=ticket.id) }}" class="ticket-card">
|
||||
<div class="ticket-card-header">
|
||||
<span class="ticket-id">#{{ ticket.id }}</span>
|
||||
<span class="badge badge-{{ ticket.status.value }}">{{ ticket.status.value.replace('_', ' ') | title }}</span>
|
||||
</div>
|
||||
<h3 class="ticket-card-title">{{ ticket.title }}</h3>
|
||||
<p class="ticket-card-desc">{{ ticket.description[:120] }}{% if ticket.description|length > 120 %}...{% endif %}</p>
|
||||
<div class="ticket-card-meta">
|
||||
<span class="badge badge-priority badge-p-{{ ticket.priority.value }}">{{ ticket.priority.value | upper }}</span>
|
||||
{% if ticket.project %}
|
||||
<span class="badge badge-project">{{ ticket.project }}</span>
|
||||
{% endif %}
|
||||
{% if ticket.assignee %}
|
||||
<span class="assignee">👤 {{ ticket.assignee }}</span>
|
||||
{% endif %}
|
||||
<span class="date">{{ ticket.created_at[:10] }}</span>
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="empty-state">
|
||||
<p>No tickets found.</p>
|
||||
<a href="{{ url_for('create_ticket') }}" class="btn btn-primary">Create the first ticket</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user