- Add previous_image_id column to apps table (migration 006)
- Save current image as previous before deploying new one
- POST /apps/{id}/rollback endpoint with handler
- Rollback stops current container, starts previous image
- Creates deployment record for rollback operations
- Rollback button in app detail UI (only when previous image exists)
- Add btn-warning CSS class for rollback button styling
fixes #71
205 lines
6.7 KiB
CSS
205 lines
6.7 KiB
CSS
@import "tailwindcss";
|
|
|
|
/* Source the templates */
|
|
@source "../../templates/**/*.html";
|
|
|
|
/* Material Design inspired theme customization */
|
|
@theme {
|
|
/* Primary colors */
|
|
--color-primary-50: #e3f2fd;
|
|
--color-primary-100: #bbdefb;
|
|
--color-primary-200: #90caf9;
|
|
--color-primary-300: #64b5f6;
|
|
--color-primary-400: #42a5f5;
|
|
--color-primary-500: #2196f3;
|
|
--color-primary-600: #1e88e5;
|
|
--color-primary-700: #1976d2;
|
|
--color-primary-800: #1565c0;
|
|
--color-primary-900: #0d47a1;
|
|
|
|
/* Error colors */
|
|
--color-error-50: #ffebee;
|
|
--color-error-500: #f44336;
|
|
--color-error-700: #d32f2f;
|
|
|
|
/* Success colors */
|
|
--color-success-50: #e8f5e9;
|
|
--color-success-500: #4caf50;
|
|
--color-success-700: #388e3c;
|
|
|
|
/* Warning colors */
|
|
--color-warning-50: #fff3e0;
|
|
--color-warning-500: #ff9800;
|
|
--color-warning-700: #f57c00;
|
|
|
|
/* Material Design elevation shadows */
|
|
--shadow-elevation-1: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
|
|
--shadow-elevation-2: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23);
|
|
--shadow-elevation-3: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23);
|
|
}
|
|
|
|
/* Material Design component styles */
|
|
@layer components {
|
|
/* Buttons - base styles inlined */
|
|
.btn-primary {
|
|
@apply inline-flex items-center justify-center px-4 py-2 rounded-md font-medium text-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed bg-primary-600 text-white hover:bg-primary-700 active:bg-primary-800 focus:ring-primary-500 shadow-elevation-1 hover:shadow-elevation-2;
|
|
}
|
|
|
|
.btn-secondary {
|
|
@apply inline-flex items-center justify-center px-4 py-2 rounded-md font-medium text-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed bg-white text-gray-700 border border-gray-300 hover:bg-gray-50 active:bg-gray-100 focus:ring-primary-500;
|
|
}
|
|
|
|
.btn-danger {
|
|
@apply inline-flex items-center justify-center px-4 py-2 rounded-md font-medium text-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed bg-error-500 text-white hover:bg-error-700 active:bg-red-800 focus:ring-red-500 shadow-elevation-1 hover:shadow-elevation-2;
|
|
}
|
|
|
|
.btn-success {
|
|
@apply inline-flex items-center justify-center px-4 py-2 rounded-md font-medium text-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed bg-success-500 text-white hover:bg-success-700 active:bg-green-800 focus:ring-green-500 shadow-elevation-1 hover:shadow-elevation-2;
|
|
}
|
|
|
|
.btn-warning {
|
|
@apply inline-flex items-center justify-center px-4 py-2 rounded-md font-medium text-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed bg-warning-500 text-white hover:bg-warning-700 active:bg-orange-800 focus:ring-orange-500 shadow-elevation-1 hover:shadow-elevation-2;
|
|
}
|
|
|
|
.btn-text {
|
|
@apply inline-flex items-center justify-center px-4 py-2 rounded-md font-medium text-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed text-primary-600 hover:bg-primary-50 active:bg-primary-100;
|
|
}
|
|
|
|
.btn-icon {
|
|
@apply p-2 rounded-full hover:bg-gray-100 active:bg-gray-200 transition-colors;
|
|
}
|
|
|
|
/* Cards */
|
|
.card {
|
|
@apply bg-white rounded-lg shadow-elevation-1 overflow-hidden;
|
|
}
|
|
|
|
.card-elevated {
|
|
@apply bg-white rounded-lg shadow-elevation-1 overflow-hidden hover:shadow-elevation-2 transition-shadow;
|
|
}
|
|
|
|
/* Form inputs - Material Design style */
|
|
.input {
|
|
@apply w-full px-4 py-3 border border-gray-300 rounded-md text-gray-900 placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-all;
|
|
}
|
|
|
|
.input-error {
|
|
@apply w-full px-4 py-3 border border-error-500 rounded-md text-gray-900 placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-error-500 focus:border-transparent transition-all;
|
|
}
|
|
|
|
.label {
|
|
@apply block text-sm font-medium text-gray-700 mb-1;
|
|
}
|
|
|
|
.form-group {
|
|
@apply mb-4;
|
|
}
|
|
|
|
/* Status badges */
|
|
.badge-success {
|
|
@apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-success-50 text-success-700;
|
|
}
|
|
|
|
.badge-warning {
|
|
@apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-warning-50 text-warning-700;
|
|
}
|
|
|
|
.badge-error {
|
|
@apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-error-50 text-error-700;
|
|
}
|
|
|
|
.badge-info {
|
|
@apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-primary-50 text-primary-700;
|
|
}
|
|
|
|
.badge-neutral {
|
|
@apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-700;
|
|
}
|
|
|
|
/* Tables */
|
|
.table {
|
|
@apply min-w-full divide-y divide-gray-200;
|
|
}
|
|
|
|
.table-header {
|
|
@apply bg-gray-50;
|
|
}
|
|
|
|
.table-header th {
|
|
@apply px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider;
|
|
}
|
|
|
|
.table-body {
|
|
@apply bg-white divide-y divide-gray-200;
|
|
}
|
|
|
|
.table-body td {
|
|
@apply px-6 py-4 whitespace-nowrap text-sm;
|
|
}
|
|
|
|
.table-row-hover:hover {
|
|
@apply bg-gray-50;
|
|
}
|
|
|
|
/* App bar / Navigation */
|
|
.app-bar {
|
|
@apply bg-white shadow-elevation-1 px-6 py-4;
|
|
}
|
|
|
|
/* Copy button styling */
|
|
.copy-field {
|
|
@apply flex items-center gap-2 bg-gray-100 rounded-md p-2 font-mono text-sm;
|
|
}
|
|
|
|
.copy-field-value {
|
|
@apply flex-1 overflow-x-auto whitespace-nowrap;
|
|
}
|
|
|
|
.copy-btn {
|
|
@apply p-2 rounded-full hover:bg-gray-200 active:bg-gray-300 transition-colors text-gray-500 hover:text-gray-700 shrink-0;
|
|
}
|
|
|
|
/* Alert / Message boxes */
|
|
.alert-error {
|
|
@apply p-4 rounded-md mb-4 bg-error-50 text-error-700 border border-error-500/20;
|
|
}
|
|
|
|
.alert-success {
|
|
@apply p-4 rounded-md mb-4 bg-success-50 text-success-700 border border-success-500/20;
|
|
}
|
|
|
|
.alert-warning {
|
|
@apply p-4 rounded-md mb-4 bg-warning-50 text-warning-700 border border-warning-500/20;
|
|
}
|
|
|
|
.alert-info {
|
|
@apply p-4 rounded-md mb-4 bg-primary-50 text-primary-700 border border-primary-500/20;
|
|
}
|
|
|
|
/* Section headers */
|
|
.section-header {
|
|
@apply flex items-center justify-between pb-4 border-b border-gray-200 mb-4;
|
|
}
|
|
|
|
.section-title {
|
|
@apply text-lg font-medium text-gray-900;
|
|
}
|
|
|
|
/* Empty state */
|
|
.empty-state {
|
|
@apply text-center py-12;
|
|
}
|
|
|
|
.empty-state-icon {
|
|
@apply mx-auto h-12 w-12 text-gray-400;
|
|
}
|
|
|
|
.empty-state-title {
|
|
@apply mt-2 text-sm font-medium text-gray-900;
|
|
}
|
|
|
|
.empty-state-description {
|
|
@apply mt-1 text-sm text-gray-500;
|
|
}
|
|
}
|