AP1.10c: Profil-Modal mit Archetyp, EFS und Owner.
All checks were successful
Deploy Development / deploy (push) Successful in 45s
Test Suite / pytest-backend (push) Successful in 2m13s
Test Suite / lint-backend (push) Successful in 2s
Test Suite / compose-smoke (push) Has been skipped
Test Suite / k6 /api/health Baseline (push) Successful in 18s
Test Suite / playwright-smoke (push) Successful in 12s
All checks were successful
Deploy Development / deploy (push) Successful in 45s
Test Suite / pytest-backend (push) Successful in 2m13s
Test Suite / lint-backend (push) Successful in 2s
Test Suite / compose-smoke (push) Has been skipped
Test Suite / k6 /api/health Baseline (push) Successful in 18s
Test Suite / playwright-smoke (push) Successful in 12s
InitiativeForm laedt Felder nach gewaehltem Archetyp; Plan-Profil zeigt Standardfelder und Zusatzfelder; actor_ref und Owner-Auswahl. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
43d30944aa
commit
dbe6f4f684
|
|
@ -1,11 +1,11 @@
|
||||||
export function FieldRenderer({ definitions, values, onChange, disabled = false }) {
|
export function FieldRenderer({ definitions, values, onChange, disabled = false, actors = [] }) {
|
||||||
if (!definitions?.length) {
|
if (!definitions?.length) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<fieldset className="field-renderer">
|
<fieldset className="field-renderer">
|
||||||
<legend className="field-renderer__legend">Zusatzfelder</legend>
|
<legend className="field-renderer__legend">Zusatzfelder (Archetyp)</legend>
|
||||||
{definitions.map((def) => (
|
{definitions.map((def) => (
|
||||||
<DynamicField
|
<DynamicField
|
||||||
key={def.field_key}
|
key={def.field_key}
|
||||||
|
|
@ -13,13 +13,14 @@ export function FieldRenderer({ definitions, values, onChange, disabled = false
|
||||||
value={values?.[def.field_key]}
|
value={values?.[def.field_key]}
|
||||||
onChange={(next) => onChange(def.field_key, next)}
|
onChange={(next) => onChange(def.field_key, next)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
actors={actors}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function DynamicField({ definition, value, onChange, disabled }) {
|
function DynamicField({ definition, value, onChange, disabled, actors = [] }) {
|
||||||
const { field_key, field_type, label, required, validation_json: validation } = definition
|
const { field_key, field_type, label, required, validation_json: validation } = definition
|
||||||
const inputId = `field-${field_key}`
|
const inputId = `field-${field_key}`
|
||||||
|
|
||||||
|
|
@ -83,6 +84,30 @@ function DynamicField({ definition, value, onChange, disabled }) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (field_type === 'actor_ref') {
|
||||||
|
return (
|
||||||
|
<label htmlFor={inputId}>
|
||||||
|
{label}
|
||||||
|
{required && ' *'}
|
||||||
|
<select
|
||||||
|
id={inputId}
|
||||||
|
name={field_key}
|
||||||
|
value={value ?? ''}
|
||||||
|
onChange={(e) => onChange(e.target.value || null)}
|
||||||
|
required={required}
|
||||||
|
disabled={disabled}
|
||||||
|
>
|
||||||
|
<option value="">—</option>
|
||||||
|
{actors.map((actor) => (
|
||||||
|
<option key={actor.id} value={actor.id}>
|
||||||
|
{actor.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const inputType =
|
const inputType =
|
||||||
field_type === 'number' ? 'number' : field_type === 'date' ? 'date' : field_type === 'url' ? 'url' : 'text'
|
field_type === 'number' ? 'number' : field_type === 'date' ? 'date' : field_type === 'url' ? 'url' : 'text'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import { INITIATIVE_STATUS_LABELS, PRIORITY_LABELS } from '../constants/status.j
|
||||||
import { INITIATIVE_ARCHETYPE_LABELS } from '../constants/initiativeArchetypes.js'
|
import { INITIATIVE_ARCHETYPE_LABELS } from '../constants/initiativeArchetypes.js'
|
||||||
import { listEntityArchetypes } from '../api/entityArchetypes.js'
|
import { listEntityArchetypes } from '../api/entityArchetypes.js'
|
||||||
import {
|
import {
|
||||||
getInitiativeFieldDefinitions,
|
|
||||||
getInitiativeFields,
|
getInitiativeFields,
|
||||||
listArchetypeFieldDefinitions,
|
listArchetypeFieldDefinitions,
|
||||||
} from '../api/entityFields.js'
|
} from '../api/entityFields.js'
|
||||||
|
|
@ -13,6 +12,7 @@ import { FieldRenderer } from './FieldRenderer.jsx'
|
||||||
export function InitiativeForm({
|
export function InitiativeForm({
|
||||||
initial = {},
|
initial = {},
|
||||||
initiativeId = null,
|
initiativeId = null,
|
||||||
|
actors = [],
|
||||||
onSubmit,
|
onSubmit,
|
||||||
onCancel,
|
onCancel,
|
||||||
busy = false,
|
busy = false,
|
||||||
|
|
@ -46,22 +46,24 @@ export function InitiativeForm({
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!archetypeKey) return undefined
|
||||||
let cancelled = false
|
let cancelled = false
|
||||||
setFieldsLoading(true)
|
setFieldsLoading(true)
|
||||||
|
|
||||||
async function loadFields() {
|
async function loadFields() {
|
||||||
try {
|
try {
|
||||||
let definitions = []
|
const definitions = await listArchetypeFieldDefinitions('initiative', archetypeKey)
|
||||||
let values = {}
|
let values = {}
|
||||||
if (initiativeId) {
|
if (initiativeId) {
|
||||||
definitions = await getInitiativeFieldDefinitions(initiativeId)
|
|
||||||
values = await getInitiativeFields(initiativeId)
|
values = await getInitiativeFields(initiativeId)
|
||||||
} else if (archetypeKey) {
|
|
||||||
definitions = await listArchetypeFieldDefinitions('initiative', archetypeKey)
|
|
||||||
}
|
}
|
||||||
|
const validKeys = new Set(definitions.map((def) => def.field_key))
|
||||||
|
const filteredValues = Object.fromEntries(
|
||||||
|
Object.entries(values || {}).filter(([key]) => validKeys.has(key)),
|
||||||
|
)
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
setFieldDefinitions(definitions)
|
setFieldDefinitions(definitions)
|
||||||
setDynamicValues(values)
|
setDynamicValues(filteredValues)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
|
|
@ -90,6 +92,7 @@ export function InitiativeForm({
|
||||||
target_state_summary: form.target_state_summary.value,
|
target_state_summary: form.target_state_summary.value,
|
||||||
status: form.status.value,
|
status: form.status.value,
|
||||||
priority: form.priority.value,
|
priority: form.priority.value,
|
||||||
|
owner_actor_id: form.owner_actor_id?.value || undefined,
|
||||||
dynamicFields: dynamicValues,
|
dynamicFields: dynamicValues,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -102,73 +105,100 @@ export function InitiativeForm({
|
||||||
const selectedArchetype = (archetypes || []).find((item) => item.key === archetypeKey)
|
const selectedArchetype = (archetypes || []).find((item) => item.key === archetypeKey)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form className="form workspace-form" onSubmit={handleSubmit}>
|
<form className="form workspace-form initiative-form" onSubmit={handleSubmit}>
|
||||||
<label>
|
<fieldset className="initiative-form__section">
|
||||||
Titel
|
<legend>Identität</legend>
|
||||||
<input name="title" defaultValue={initial.title || ''} required maxLength={255} />
|
<label>
|
||||||
</label>
|
Titel
|
||||||
<label>
|
<input name="title" defaultValue={initial.title || ''} required maxLength={255} />
|
||||||
Archetyp
|
</label>
|
||||||
<select
|
<label>
|
||||||
name="archetype_key"
|
Archetyp
|
||||||
value={archetypeKey}
|
<select
|
||||||
onChange={(e) => setArchetypeKey(e.target.value)}
|
name="archetype_key"
|
||||||
disabled={!archetypes}
|
value={archetypeKey}
|
||||||
>
|
onChange={(e) => setArchetypeKey(e.target.value)}
|
||||||
{(archetypes || []).map((item) => (
|
disabled={!archetypes}
|
||||||
<option key={item.key} value={item.key}>
|
>
|
||||||
{item.label}
|
{(archetypes || []).map((item) => (
|
||||||
</option>
|
<option key={item.key} value={item.key}>
|
||||||
))}
|
{item.label}
|
||||||
</select>
|
</option>
|
||||||
{selectedArchetype?.description && (
|
))}
|
||||||
<span className="muted form-hint">{selectedArchetype.description}</span>
|
</select>
|
||||||
|
{selectedArchetype?.description && (
|
||||||
|
<span className="muted form-hint">{selectedArchetype.description}</span>
|
||||||
|
)}
|
||||||
|
</label>
|
||||||
|
{actors.length > 0 && (
|
||||||
|
<label>
|
||||||
|
Verantwortlich (Owner)
|
||||||
|
<select name="owner_actor_id" defaultValue={initial.owner_actor_id || ''}>
|
||||||
|
<option value="">—</option>
|
||||||
|
{actors.map((actor) => (
|
||||||
|
<option key={actor.id} value={actor.id}>
|
||||||
|
{actor.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
)}
|
)}
|
||||||
</label>
|
</fieldset>
|
||||||
<label>
|
|
||||||
Kurzbeschreibung (Ziel)
|
<fieldset className="initiative-form__section">
|
||||||
<textarea name="goal" rows={2} defaultValue={initial.goal || ''} />
|
<legend>Programm</legend>
|
||||||
</label>
|
<label>
|
||||||
<label>
|
Kurzbeschreibung (Ziel)
|
||||||
Vision
|
<textarea name="goal" rows={2} defaultValue={initial.goal || ''} />
|
||||||
<textarea name="vision" rows={4} defaultValue={initial.vision || ''} />
|
</label>
|
||||||
</label>
|
<label>
|
||||||
<label>
|
Vision
|
||||||
Zielzustand (Kurzfassung)
|
<textarea name="vision" rows={4} defaultValue={initial.vision || ''} />
|
||||||
<textarea
|
</label>
|
||||||
name="target_state_summary"
|
<label>
|
||||||
rows={2}
|
Zielzustand (Kurzfassung)
|
||||||
defaultValue={initial.target_state_summary || ''}
|
<textarea
|
||||||
/>
|
name="target_state_summary"
|
||||||
</label>
|
rows={2}
|
||||||
|
defaultValue={initial.target_state_summary || ''}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
<FieldRenderer
|
<FieldRenderer
|
||||||
definitions={fieldDefinitions}
|
definitions={fieldDefinitions}
|
||||||
values={dynamicValues}
|
values={dynamicValues}
|
||||||
onChange={handleDynamicChange}
|
onChange={handleDynamicChange}
|
||||||
disabled={busy || fieldsLoading}
|
disabled={busy || fieldsLoading}
|
||||||
|
actors={actors}
|
||||||
/>
|
/>
|
||||||
<div className="form-row form-row--2">
|
|
||||||
<label>
|
<fieldset className="initiative-form__section">
|
||||||
Status
|
<legend>Steuerung</legend>
|
||||||
<select name="status" defaultValue={initial.status || 'active'}>
|
<div className="form-row form-row--2">
|
||||||
{INITIATIVE_STATUSES.map((s) => (
|
<label>
|
||||||
<option key={s} value={s}>
|
Status
|
||||||
{INITIATIVE_STATUS_LABELS[s]}
|
<select name="status" defaultValue={initial.status || 'active'}>
|
||||||
</option>
|
{INITIATIVE_STATUSES.map((s) => (
|
||||||
))}
|
<option key={s} value={s}>
|
||||||
</select>
|
{INITIATIVE_STATUS_LABELS[s]}
|
||||||
</label>
|
</option>
|
||||||
<label>
|
))}
|
||||||
Priorität
|
</select>
|
||||||
<select name="priority" defaultValue={initial.priority || 'normal'}>
|
</label>
|
||||||
{PRIORITIES.map((p) => (
|
<label>
|
||||||
<option key={p} value={p}>
|
Priorität
|
||||||
{PRIORITY_LABELS[p]}
|
<select name="priority" defaultValue={initial.priority || 'normal'}>
|
||||||
</option>
|
{PRIORITIES.map((p) => (
|
||||||
))}
|
<option key={p} value={p}>
|
||||||
</select>
|
{PRIORITY_LABELS[p]}
|
||||||
</label>
|
</option>
|
||||||
</div>
|
))}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
<div className="form-actions">
|
<div className="form-actions">
|
||||||
<button type="submit" className="btn btn-primary" disabled={busy || !formReady}>
|
<button type="submit" className="btn btn-primary" disabled={busy || !formReady}>
|
||||||
{busy ? 'Speichern …' : submitLabel}
|
{busy ? 'Speichern …' : submitLabel}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { RequireInitiativeScope } from '../../components/RequireInitiativeScope.jsx'
|
import { RequireInitiativeScope } from '../../components/RequireInitiativeScope.jsx'
|
||||||
import { ScopedInitiativeProvider } from '../../layout/ScopedInitiativeProvider.jsx'
|
import { ScopedInitiativeProvider } from '../../layout/ScopedInitiativeProvider.jsx'
|
||||||
|
import { ArchetypeBadge } from '../../components/ArchetypeBadge.jsx'
|
||||||
import { StatusBadge } from '../../components/StatusBadge.jsx'
|
import { StatusBadge } from '../../components/StatusBadge.jsx'
|
||||||
import { LoadingState } from '../../components/LoadingState.jsx'
|
import { LoadingState } from '../../components/LoadingState.jsx'
|
||||||
import { Modal } from '../../components/Modal.jsx'
|
import { Modal } from '../../components/Modal.jsx'
|
||||||
|
|
@ -17,13 +18,15 @@ import {
|
||||||
getInitiativeFields,
|
getInitiativeFields,
|
||||||
} from '../../api/entityFields.js'
|
} from '../../api/entityFields.js'
|
||||||
|
|
||||||
function DynamicFieldsDisplay({ initiativeId }) {
|
function DynamicFieldsDisplay({ initiativeId, refreshKey = 0 }) {
|
||||||
const [definitions, setDefinitions] = useState([])
|
const [definitions, setDefinitions] = useState([])
|
||||||
const [values, setValues] = useState(null)
|
const [values, setValues] = useState(null)
|
||||||
|
const [loading, setLoading] = useState(true)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let cancelled = false
|
let cancelled = false
|
||||||
async function load() {
|
async function load() {
|
||||||
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
const [defs, fieldValues] = await Promise.all([
|
const [defs, fieldValues] = await Promise.all([
|
||||||
getInitiativeFieldDefinitions(initiativeId),
|
getInitiativeFieldDefinitions(initiativeId),
|
||||||
|
|
@ -38,15 +41,21 @@ function DynamicFieldsDisplay({ initiativeId }) {
|
||||||
setDefinitions([])
|
setDefinitions([])
|
||||||
setValues({})
|
setValues({})
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
if (!cancelled) setLoading(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
load()
|
load()
|
||||||
return () => {
|
return () => {
|
||||||
cancelled = true
|
cancelled = true
|
||||||
}
|
}
|
||||||
}, [initiativeId])
|
}, [initiativeId, refreshKey])
|
||||||
|
|
||||||
if (!definitions.length || values === null) {
|
if (loading || values === null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!definitions.length) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -57,15 +66,25 @@ function DynamicFieldsDisplay({ initiativeId }) {
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!visible.length) {
|
if (!visible.length) {
|
||||||
return null
|
return (
|
||||||
|
<div className="plan-profile__field">
|
||||||
|
<h3 className="plan-profile__label">Zusatzfelder (Archetyp)</h3>
|
||||||
|
<p className="muted">Noch keine Werte für die Felder dieses Archetyps.</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return visible.map((def) => (
|
return (
|
||||||
<div key={def.field_key} className="plan-profile__field">
|
<div className="plan-profile__section">
|
||||||
<h3 className="plan-profile__label">{def.label}</h3>
|
<h3 className="plan-profile__section-title">Zusatzfelder (Archetyp)</h3>
|
||||||
<p>{formatFieldValue(def, values[def.field_key])}</p>
|
{visible.map((def) => (
|
||||||
|
<div key={def.field_key} className="plan-profile__field">
|
||||||
|
<h4 className="plan-profile__label">{def.label}</h4>
|
||||||
|
<p>{formatFieldValue(def, values[def.field_key])}</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatFieldValue(definition, value) {
|
function formatFieldValue(definition, value) {
|
||||||
|
|
@ -91,6 +110,7 @@ function PlanProfileInner() {
|
||||||
projects,
|
projects,
|
||||||
} = ops
|
} = ops
|
||||||
const [editing, setEditing] = useState(false)
|
const [editing, setEditing] = useState(false)
|
||||||
|
const [fieldsRefreshKey, setFieldsRefreshKey] = useState(0)
|
||||||
const canManage = capabilities.has('kairo.initiative.manage')
|
const canManage = capabilities.has('kairo.initiative.manage')
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
|
|
@ -110,6 +130,7 @@ function PlanProfileInner() {
|
||||||
const ok = await ops.handleUpdateInitiative(payload)
|
const ok = await ops.handleUpdateInitiative(payload)
|
||||||
if (ok) {
|
if (ok) {
|
||||||
refreshInitiativeMeta()
|
refreshInitiativeMeta()
|
||||||
|
setFieldsRefreshKey((key) => key + 1)
|
||||||
setEditing(false)
|
setEditing(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -118,7 +139,13 @@ function PlanProfileInner() {
|
||||||
<>
|
<>
|
||||||
<section className="card plan-profile">
|
<section className="card plan-profile">
|
||||||
<header className="plan-profile__header">
|
<header className="plan-profile__header">
|
||||||
<h2 className="card-title">{initiative.title}</h2>
|
<div>
|
||||||
|
<h2 className="card-title">{initiative.title}</h2>
|
||||||
|
<ArchetypeBadge
|
||||||
|
archetypeKey={initiative.archetype_key}
|
||||||
|
archetypes={initiativeArchetypes}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className="plan-profile__header-actions">
|
<div className="plan-profile__header-actions">
|
||||||
<StatusBadge kind="initiative" status={initiative.status} />
|
<StatusBadge kind="initiative" status={initiative.status} />
|
||||||
{canManage && (
|
{canManage && (
|
||||||
|
|
@ -165,27 +192,29 @@ function PlanProfileInner() {
|
||||||
<p>{initiative.goal}</p>
|
<p>{initiative.goal}</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<p className="muted">Noch keine Kurzbeschreibung hinterlegt.</p>
|
<p className="muted plan-profile__empty-hint">Noch keine Kurzbeschreibung hinterlegt.</p>
|
||||||
)}
|
)}
|
||||||
{initiative.vision && (
|
<div className="plan-profile__field">
|
||||||
<div className="plan-profile__field">
|
<h3 className="plan-profile__label">Vision</h3>
|
||||||
<h3 className="plan-profile__label">Vision</h3>
|
<p>{initiative.vision?.trim() ? initiative.vision : '—'}</p>
|
||||||
<p>{initiative.vision}</p>
|
</div>
|
||||||
</div>
|
<div className="plan-profile__field">
|
||||||
)}
|
<h3 className="plan-profile__label">Zielzustand (Kurzfassung)</h3>
|
||||||
{initiative.target_state_summary && (
|
<p>
|
||||||
<div className="plan-profile__field">
|
{initiative.target_state_summary?.trim() ? initiative.target_state_summary : '—'}
|
||||||
<h3 className="plan-profile__label">Zielzustand</h3>
|
</p>
|
||||||
<p>{initiative.target_state_summary}</p>
|
</div>
|
||||||
</div>
|
<DynamicFieldsDisplay
|
||||||
)}
|
initiativeId={initiative.id}
|
||||||
<DynamicFieldsDisplay initiativeId={initiative.id} key={editing ? 'closed' : 'open'} />
|
refreshKey={fieldsRefreshKey}
|
||||||
|
/>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<Modal open={editing} title="Vorhaben bearbeiten" onClose={() => setEditing(false)} size="lg">
|
<Modal open={editing} title="Vorhaben bearbeiten" onClose={() => setEditing(false)} size="lg">
|
||||||
<InitiativeForm
|
<InitiativeForm
|
||||||
initiativeId={initiative.id}
|
initiativeId={initiative.id}
|
||||||
initial={initiative}
|
initial={initiative}
|
||||||
|
actors={actors}
|
||||||
onSubmit={handleSave}
|
onSubmit={handleSave}
|
||||||
onCancel={() => setEditing(false)}
|
onCancel={() => setEditing(false)}
|
||||||
busy={formBusy}
|
busy={formBusy}
|
||||||
|
|
|
||||||
|
|
@ -1595,9 +1595,37 @@
|
||||||
background: var(--jk-surface-subtle, #f8fafc);
|
background: var(--jk-surface-subtle, #f8fafc);
|
||||||
}
|
}
|
||||||
|
|
||||||
.plan-profile__steering-edit {
|
.initiative-form__section {
|
||||||
|
border: none;
|
||||||
|
margin: 0 0 1.25rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.initiative-form__section legend {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-profile__section-title {
|
||||||
|
margin: 1.25rem 0 0.75rem;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-profile__empty-hint {
|
||||||
margin: 0 0 1rem;
|
margin: 0 0 1rem;
|
||||||
max-width: 28rem;
|
}
|
||||||
|
|
||||||
|
.field-renderer {
|
||||||
|
border: none;
|
||||||
|
margin: 0 0 1.25rem;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.field-renderer__legend {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.method-profile-select {
|
.method-profile-select {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user