moved some basic value lists to database
This commit is contained in:
@@ -3307,3 +3307,128 @@ func getStandBonusPoints(stand string) map[string]int {
|
||||
return make(map[string]int)
|
||||
}
|
||||
}
|
||||
|
||||
// GetDatasheetOptions returns all available options for datasheet select boxes
|
||||
func GetDatasheetOptions(c *gin.Context) {
|
||||
logger.Debug("GetDatasheetOptions aufgerufen")
|
||||
|
||||
characterID := c.Param("id")
|
||||
|
||||
// Load character to get their weapon skills
|
||||
var character models.Char
|
||||
err := character.FirstID(characterID)
|
||||
if err != nil {
|
||||
logger.Error("GetDatasheetOptions: Charakter nicht gefunden - ID: %s, Error: %s", characterID, err.Error())
|
||||
respondWithError(c, http.StatusNotFound, "Character not found")
|
||||
return
|
||||
}
|
||||
|
||||
// Get all available weapons from database
|
||||
var allWeapons []models.Weapon
|
||||
if err := database.DB.Find(&allWeapons).Error; err != nil {
|
||||
logger.Error("GetDatasheetOptions: Fehler beim Laden der Waffen: %s", err.Error())
|
||||
respondWithError(c, http.StatusInternalServerError, "Failed to load weapons")
|
||||
return
|
||||
}
|
||||
|
||||
// Filter weapons based on character's weapon skills
|
||||
characterWeaponSkills := make(map[string]bool)
|
||||
for _, skill := range character.Waffenfertigkeiten {
|
||||
characterWeaponSkills[skill.Name] = true
|
||||
}
|
||||
|
||||
availableWeapons := []string{}
|
||||
for _, weapon := range allWeapons {
|
||||
if characterWeaponSkills[weapon.SkillRequired] {
|
||||
availableWeapons = append(availableWeapons, weapon.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// Load misc lookup data from database
|
||||
genders, err := gsmaster.GetMiscLookupByKey("gender")
|
||||
if err != nil {
|
||||
logger.Error("GetDatasheetOptions: Fehler beim Laden der Geschlechter: %s", err.Error())
|
||||
respondWithError(c, http.StatusInternalServerError, "Failed to load genders")
|
||||
return
|
||||
}
|
||||
|
||||
races, err := gsmaster.GetMiscLookupByKey("races")
|
||||
if err != nil {
|
||||
logger.Error("GetDatasheetOptions: Fehler beim Laden der Rassen: %s", err.Error())
|
||||
respondWithError(c, http.StatusInternalServerError, "Failed to load races")
|
||||
return
|
||||
}
|
||||
|
||||
origins, err := gsmaster.GetMiscLookupByKey("origins")
|
||||
if err != nil {
|
||||
logger.Error("GetDatasheetOptions: Fehler beim Laden der Herkünfte: %s", err.Error())
|
||||
respondWithError(c, http.StatusInternalServerError, "Failed to load origins")
|
||||
return
|
||||
}
|
||||
|
||||
socialClasses, err := gsmaster.GetMiscLookupByKey("social_classes")
|
||||
if err != nil {
|
||||
logger.Error("GetDatasheetOptions: Fehler beim Laden der Stände: %s", err.Error())
|
||||
respondWithError(c, http.StatusInternalServerError, "Failed to load social classes")
|
||||
return
|
||||
}
|
||||
|
||||
faiths, err := gsmaster.GetMiscLookupByKey("faiths")
|
||||
if err != nil {
|
||||
logger.Error("GetDatasheetOptions: Fehler beim Laden der Glaubensrichtungen: %s", err.Error())
|
||||
respondWithError(c, http.StatusInternalServerError, "Failed to load faiths")
|
||||
return
|
||||
}
|
||||
|
||||
handedness, err := gsmaster.GetMiscLookupByKey("handedness")
|
||||
if err != nil {
|
||||
logger.Error("GetDatasheetOptions: Fehler beim Laden der Händigkeiten: %s", err.Error())
|
||||
respondWithError(c, http.StatusInternalServerError, "Failed to load handedness")
|
||||
return
|
||||
}
|
||||
|
||||
// Convert to string arrays
|
||||
genderValues := make([]string, len(genders))
|
||||
for i, g := range genders {
|
||||
genderValues[i] = g.Value
|
||||
}
|
||||
|
||||
raceValues := make([]string, len(races))
|
||||
for i, r := range races {
|
||||
raceValues[i] = r.Value
|
||||
}
|
||||
|
||||
originValues := make([]string, len(origins))
|
||||
for i, o := range origins {
|
||||
originValues[i] = o.Value
|
||||
}
|
||||
|
||||
socialClassValues := make([]string, len(socialClasses))
|
||||
for i, sc := range socialClasses {
|
||||
socialClassValues[i] = sc.Value
|
||||
}
|
||||
|
||||
faithValues := make([]string, len(faiths))
|
||||
for i, f := range faiths {
|
||||
faithValues[i] = f.Value
|
||||
}
|
||||
|
||||
handednessValues := make([]string, len(handedness))
|
||||
for i, h := range handedness {
|
||||
handednessValues[i] = h.Value
|
||||
}
|
||||
|
||||
// Return all options
|
||||
options := gin.H{
|
||||
"gender": genderValues,
|
||||
"races": raceValues,
|
||||
"origins": originValues,
|
||||
"social_classes": socialClassValues,
|
||||
"faiths": faithValues,
|
||||
"handedness": handednessValues,
|
||||
"specializations": availableWeapons,
|
||||
}
|
||||
|
||||
logger.Debug("GetDatasheetOptions: Erfolgreich geladen - %d verfügbare Waffen", len(availableWeapons))
|
||||
c.JSON(http.StatusOK, options)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
@@ -975,3 +976,142 @@ func TestListCharacters(t *testing.T) {
|
||||
assert.Equal(t, 0, len(response.SelfOwned), "Should return empty list for userID 0")
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetDatasheetOptions(t *testing.T) {
|
||||
// Setup test environment
|
||||
original := os.Getenv("ENVIRONMENT")
|
||||
os.Setenv("ENVIRONMENT", "test")
|
||||
t.Cleanup(func() {
|
||||
if original != "" {
|
||||
os.Setenv("ENVIRONMENT", original)
|
||||
} else {
|
||||
os.Unsetenv("ENVIRONMENT")
|
||||
}
|
||||
})
|
||||
|
||||
// Setup test database
|
||||
database.SetupTestDB(true, true)
|
||||
defer database.ResetTestDB()
|
||||
|
||||
err := models.MigrateStructure()
|
||||
assert.NoError(t, err)
|
||||
|
||||
/*
|
||||
// Populate misc lookup data
|
||||
err = models.PopulateMiscLookupData()
|
||||
assert.NoError(t, err)
|
||||
*/
|
||||
|
||||
// Create test character with weapon skill
|
||||
testChar := &models.Char{
|
||||
BamortBase: models.BamortBase{
|
||||
Name: "Test Character",
|
||||
},
|
||||
Typ: "Krieger",
|
||||
Rasse: "Mensch",
|
||||
Waffenfertigkeiten: []models.SkWaffenfertigkeit{
|
||||
{
|
||||
SkFertigkeit: models.SkFertigkeit{
|
||||
BamortCharTrait: models.BamortCharTrait{
|
||||
BamortBase: models.BamortBase{
|
||||
Name: "Langschwert",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
err = testChar.Create()
|
||||
assert.NoError(t, err)
|
||||
assert.NotZero(t, testChar.ID, "Character ID should be set after Create")
|
||||
|
||||
// Setup Gin context
|
||||
gin.SetMode(gin.TestMode)
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
// Use string conversion of actual character ID
|
||||
c.Params = gin.Params{{Key: "id", Value: fmt.Sprintf("%d", testChar.ID)}}
|
||||
|
||||
// Call the handler
|
||||
GetDatasheetOptions(c)
|
||||
|
||||
// Assert response
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
|
||||
var response map[string]interface{}
|
||||
err = json.Unmarshal(w.Body.Bytes(), &response)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Verify all expected keys exist
|
||||
assert.Contains(t, response, "gender")
|
||||
assert.Contains(t, response, "races")
|
||||
assert.Contains(t, response, "origins")
|
||||
assert.Contains(t, response, "social_classes")
|
||||
assert.Contains(t, response, "faiths")
|
||||
assert.Contains(t, response, "handedness")
|
||||
assert.Contains(t, response, "specializations")
|
||||
|
||||
// Verify data from database
|
||||
genders := response["gender"].([]interface{})
|
||||
assert.Equal(t, 3, len(genders))
|
||||
assert.Contains(t, genders, "divers")
|
||||
assert.Contains(t, genders, "männlich")
|
||||
assert.Contains(t, genders, "weiblich")
|
||||
|
||||
races := response["races"].([]interface{})
|
||||
assert.Equal(t, 5, len(races))
|
||||
assert.Contains(t, races, "Elf")
|
||||
assert.Contains(t, races, "Mensch")
|
||||
|
||||
origins := response["origins"].([]interface{})
|
||||
assert.Equal(t, 15, len(origins))
|
||||
assert.Contains(t, origins, "Albai")
|
||||
|
||||
socialClasses := response["social_classes"].([]interface{})
|
||||
assert.Equal(t, 3, len(socialClasses))
|
||||
assert.Contains(t, socialClasses, "Adel")
|
||||
assert.Contains(t, socialClasses, "Mittelschicht")
|
||||
|
||||
faiths := response["faiths"].([]interface{})
|
||||
assert.Equal(t, 5, len(faiths))
|
||||
assert.Contains(t, faiths, "Druide")
|
||||
assert.Contains(t, faiths, "Keine")
|
||||
|
||||
handedness := response["handedness"].([]interface{})
|
||||
assert.Equal(t, 3, len(handedness))
|
||||
assert.Contains(t, handedness, "beidhändig")
|
||||
assert.Contains(t, handedness, "links")
|
||||
assert.Contains(t, handedness, "rechts")
|
||||
}
|
||||
|
||||
func TestGetDatasheetOptions_CharacterNotFound(t *testing.T) {
|
||||
// Setup test environment
|
||||
original := os.Getenv("ENVIRONMENT")
|
||||
os.Setenv("ENVIRONMENT", "test")
|
||||
t.Cleanup(func() {
|
||||
if original != "" {
|
||||
os.Setenv("ENVIRONMENT", original)
|
||||
} else {
|
||||
os.Unsetenv("ENVIRONMENT")
|
||||
}
|
||||
})
|
||||
|
||||
// Setup test database
|
||||
database.SetupTestDB(true, true)
|
||||
defer database.ResetTestDB()
|
||||
|
||||
err := models.MigrateStructure()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Setup Gin context with non-existent character ID
|
||||
gin.SetMode(gin.TestMode)
|
||||
w := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(w)
|
||||
c.Params = gin.Params{{Key: "id", Value: "99999"}}
|
||||
|
||||
// Call the handler
|
||||
GetDatasheetOptions(c)
|
||||
|
||||
// Assert error response
|
||||
assert.Equal(t, http.StatusNotFound, w.Code)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ func RegisterRoutes(r *gin.RouterGroup) {
|
||||
charGrp.PUT("/:id", UpdateCharacter)
|
||||
charGrp.DELETE("/:id", DeleteCharacter)
|
||||
charGrp.PUT("/:id/image", UpdateCharacterImage)
|
||||
charGrp.GET("/:id/datasheet-options", GetDatasheetOptions)
|
||||
|
||||
// Erfahrung und Vermögen
|
||||
charGrp.GET("/:id/experience-wealth", GetCharacterExperienceAndWealth) // NewSystem
|
||||
|
||||
@@ -59,6 +59,16 @@ func main() {
|
||||
database.ConnectDatabase()
|
||||
logger.Info("Datenbankverbindung erfolgreich")
|
||||
|
||||
/*
|
||||
// Populate initial misc lookup data
|
||||
logger.Debug("Initialisiere Misc-Lookup-Daten...")
|
||||
if err := models.PopulateMiscLookupData(); err != nil {
|
||||
logger.Warn("Fehler beim Initialisieren der Misc-Lookup-Daten: %s", err.Error())
|
||||
} else {
|
||||
logger.Info("Misc-Lookup-Daten erfolgreich initialisiert")
|
||||
}
|
||||
*/
|
||||
|
||||
// Initialize PDF templates
|
||||
logger.Debug("Initialisiere PDF-Templates...")
|
||||
if err := pdfrender.InitializeTemplates("/app/default_templates", cfg.TemplatesDir); err != nil {
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
package gsmaster
|
||||
|
||||
import (
|
||||
"bamort/database"
|
||||
"bamort/models"
|
||||
)
|
||||
|
||||
// GetMiscLookupByKey retrieves all values for a given key
|
||||
func GetMiscLookupByKey(key string) ([]models.MiscLookup, error) {
|
||||
var items []models.MiscLookup
|
||||
err := database.DB.Where("`key` = ?", key).Order("value ASC").Find(&items).Error
|
||||
return items, err
|
||||
}
|
||||
|
||||
/*
|
||||
// PopulateMiscLookupData populates initial misc lookup data if table is empty
|
||||
func PopulateMiscLookupData() error {
|
||||
// Check if data already exists
|
||||
var count int64
|
||||
if err := database.DB.Model(&models.MiscLookup{}).Count(&count).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if count > 0 {
|
||||
return nil // Data already exists
|
||||
}
|
||||
|
||||
// Define initial data
|
||||
initialData := []struct {
|
||||
key string
|
||||
values []string
|
||||
}{
|
||||
{
|
||||
key: "gender",
|
||||
values: []string{"männlich", "weiblich", "divers"},
|
||||
},
|
||||
{
|
||||
key: "races",
|
||||
values: []string{"Mensch", "Elf", "Zwerg", "Gnom", "Halbling"},
|
||||
},
|
||||
{
|
||||
key: "origins",
|
||||
values: []string{
|
||||
"Albai", "Aran", "Chryseia", "Clanngadarn", "Erainn",
|
||||
"Eschar", "Fuardain", "Ikengabecken", "KanThaiPan", "Küstenstaaten",
|
||||
"Moravod", "Nahuatlan", "Rawindra", "Twyneddin", "Valian",
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "social_classes",
|
||||
values: []string{"Volk", "Mittelschicht", "Adel"},
|
||||
},
|
||||
{
|
||||
key: "faiths",
|
||||
values: []string{"Keine", "Nathir", "Deis Albai", "Mahal", "Druide"},
|
||||
},
|
||||
{
|
||||
key: "handedness",
|
||||
values: []string{"rechts", "links", "beidhändig"},
|
||||
},
|
||||
}
|
||||
|
||||
// Insert data
|
||||
for _, item := range initialData {
|
||||
for _, value := range item.values {
|
||||
misc := models.MiscLookup{
|
||||
Key: item.key,
|
||||
Value: value,
|
||||
}
|
||||
if err := database.DB.Create(&misc).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,123 @@
|
||||
package gsmaster
|
||||
|
||||
import (
|
||||
"bamort/database"
|
||||
"bamort/models"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMiscLookup_TableName(t *testing.T) {
|
||||
misc := models.MiscLookup{}
|
||||
assert.Equal(t, "gsm_misc", misc.TableName())
|
||||
}
|
||||
|
||||
func TestMiscLookup_CreateAndRetrieve(t *testing.T) {
|
||||
database.SetupTestDB()
|
||||
|
||||
// Create test data
|
||||
testData := []models.MiscLookup{
|
||||
{Key: "gender", Value: "männlich"},
|
||||
{Key: "gender", Value: "weiblich"},
|
||||
{Key: "races", Value: "Mensch"},
|
||||
{Key: "races", Value: "Elf"},
|
||||
}
|
||||
|
||||
// Insert test data
|
||||
for _, item := range testData {
|
||||
err := database.DB.Create(&item).Error
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// Retrieve by key
|
||||
genders, err := GetMiscLookupByKey("gender")
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, genders, 2)
|
||||
assert.Equal(t, "männlich", genders[0].Value)
|
||||
assert.Equal(t, "weiblich", genders[1].Value)
|
||||
|
||||
races, err := GetMiscLookupByKey("races")
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, races, 2)
|
||||
}
|
||||
|
||||
func TestGetMiscLookupByKey_NotFound(t *testing.T) {
|
||||
database.SetupTestDB()
|
||||
|
||||
items, err := GetMiscLookupByKey("nonexistent")
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, items)
|
||||
}
|
||||
|
||||
func TestMiscLookup_WithSourceInfo(t *testing.T) {
|
||||
database.SetupTestDB()
|
||||
|
||||
misc := models.MiscLookup{
|
||||
Key: "test_key",
|
||||
Value: "test_value",
|
||||
SourceID: 1,
|
||||
PageNumber: 42,
|
||||
}
|
||||
|
||||
err := database.DB.Create(&misc).Error
|
||||
require.NoError(t, err)
|
||||
assert.NotZero(t, misc.ID)
|
||||
|
||||
// Retrieve and verify
|
||||
var retrieved models.MiscLookup
|
||||
err = database.DB.First(&retrieved, misc.ID).Error
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "test_key", retrieved.Key)
|
||||
assert.Equal(t, "test_value", retrieved.Value)
|
||||
assert.Equal(t, uint(1), retrieved.SourceID)
|
||||
assert.Equal(t, 42, retrieved.PageNumber)
|
||||
}
|
||||
|
||||
/*
|
||||
func TestPopulateMiscLookupData(t *testing.T) {
|
||||
database.SetupTestDB()
|
||||
|
||||
// First population should succeed
|
||||
err := PopulateMiscLookupData()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify all keys have data
|
||||
expectedCounts := map[string]int{
|
||||
"gender": 3,
|
||||
"races": 5,
|
||||
"origins": 15,
|
||||
"social_classes": 3,
|
||||
"faiths": 5,
|
||||
"handedness": 3,
|
||||
}
|
||||
|
||||
for key, expectedCount := range expectedCounts {
|
||||
items, err := GetMiscLookupByKey(key)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, items, expectedCount, "Expected %d items for key %s", expectedCount, key)
|
||||
}
|
||||
|
||||
// Verify specific values
|
||||
genders, _ := GetMiscLookupByKey("gender")
|
||||
assert.Contains(t, []string{"männlich", "weiblich", "divers"}, genders[0].Value)
|
||||
|
||||
races, _ := GetMiscLookupByKey("races")
|
||||
raceValues := make([]string, len(races))
|
||||
for i, r := range races {
|
||||
raceValues[i] = r.Value
|
||||
}
|
||||
assert.Contains(t, raceValues, "Mensch")
|
||||
assert.Contains(t, raceValues, "Elf")
|
||||
|
||||
// Second population should not duplicate data
|
||||
err = PopulateMiscLookupData()
|
||||
require.NoError(t, err)
|
||||
|
||||
var totalCount int64
|
||||
err = database.DB.Model(&MiscLookup{}).Count(&totalCount).Error
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(34), totalCount, "Should not duplicate data on second population")
|
||||
}
|
||||
*/
|
||||
@@ -61,6 +61,7 @@ func gsMasterMigrateStructure(db ...*gorm.DB) error {
|
||||
&Container{},
|
||||
&Transportation{},
|
||||
&Believe{},
|
||||
&MiscLookup{},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -128,6 +128,15 @@ type Believe struct {
|
||||
PageNumber int `json:"page_number,omitempty"` // Seitenzahl im Quellenbuch
|
||||
}
|
||||
|
||||
// MiscLookup represents miscellaneous lookup values like gender, race, origin, etc.
|
||||
type MiscLookup struct {
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Key string `gorm:"column:key;type:varchar(50);index;not null" json:"key"`
|
||||
Value string `gorm:"type:varchar(255);not null" json:"value"`
|
||||
SourceID uint `json:"source_id,omitempty"`
|
||||
PageNumber int `json:"page_number,omitempty"`
|
||||
}
|
||||
|
||||
func (object *Skill) TableName() string {
|
||||
dbPrefix := "gsm"
|
||||
return dbPrefix + "_" + "skills"
|
||||
@@ -669,3 +678,8 @@ func GetBelievesByActiveSources(gameSystem string) ([]Believe, error) {
|
||||
Find(&believes).Error
|
||||
return believes, err
|
||||
}
|
||||
|
||||
// TableName specifies the table name for MiscLookup
|
||||
func (MiscLookup) TableName() string {
|
||||
return "gsm_misc"
|
||||
}
|
||||
|
||||
@@ -49,7 +49,9 @@
|
||||
@dblclick="startEditProp('gender', character.gender)"
|
||||
class="editable-prop"
|
||||
>{{ character.gender || 'x' }}</span>
|
||||
<input v-else v-model="editPropValue" @blur="saveProp('gender')" @keyup.enter="saveProp('gender')" @keyup.esc="cancelEditProp" ref="propInput" class="prop-input" />
|
||||
<select v-else v-model="editPropValue" @blur="saveProp('gender')" @keyup.enter="saveProp('gender')" @keyup.esc="cancelEditProp" ref="propInput" class="prop-input">
|
||||
<option v-for="option in getSelectOptions('gender')" :key="option" :value="option">{{ option }}</option>
|
||||
</select>
|
||||
),
|
||||
Grad:
|
||||
<span
|
||||
@@ -64,21 +66,27 @@
|
||||
@dblclick="startEditProp('rasse', character.rasse)"
|
||||
class="editable-prop"
|
||||
>{{ character.rasse || 'x' }}</span>
|
||||
<input v-else v-model="editPropValue" @blur="saveProp('rasse')" @keyup.enter="saveProp('rasse')" @keyup.esc="cancelEditProp" ref="propInput" class="prop-input" />,
|
||||
<select v-else v-model="editPropValue" @blur="saveProp('rasse')" @keyup.enter="saveProp('rasse')" @keyup.esc="cancelEditProp" ref="propInput" class="prop-input">
|
||||
<option v-for="option in getSelectOptions('rasse')" :key="option" :value="option">{{ option }}</option>
|
||||
</select>,
|
||||
Heimat:
|
||||
<span
|
||||
v-if="editingProp !== 'origin'"
|
||||
@dblclick="startEditProp('origin', character.origin)"
|
||||
class="editable-prop"
|
||||
>{{ character.origin || '-' }}</span>
|
||||
<input v-else v-model="editPropValue" @blur="saveProp('origin')" @keyup.enter="saveProp('origin')" @keyup.esc="cancelEditProp" ref="propInput" class="prop-input" />,
|
||||
<select v-else v-model="editPropValue" @blur="saveProp('origin')" @keyup.enter="saveProp('origin')" @keyup.esc="cancelEditProp" ref="propInput" class="prop-input">
|
||||
<option v-for="option in getSelectOptions('origin')" :key="option" :value="option">{{ option }}</option>
|
||||
</select>,
|
||||
Stand:
|
||||
<span
|
||||
v-if="editingProp !== 'social_class'"
|
||||
@dblclick="startEditProp('social_class', character.social_class)"
|
||||
class="editable-prop"
|
||||
>{{ character.social_class || '-' }}</span>
|
||||
<input v-else v-model="editPropValue" @blur="saveProp('social_class')" @keyup.enter="saveProp('social_class')" @keyup.esc="cancelEditProp" ref="propInput" class="prop-input" />.
|
||||
<select v-else v-model="editPropValue" @blur="saveProp('social_class')" @keyup.enter="saveProp('social_class')" @keyup.esc="cancelEditProp" ref="propInput" class="prop-input">
|
||||
<option v-for="option in getSelectOptions('social_class')" :key="option" :value="option">{{ option }}</option>
|
||||
</select>.
|
||||
</p>
|
||||
<p v-if="character.rasse==='Zwerg'">
|
||||
Hort für Grad {{ character.grad || 'x' }}: 125 GS, für nächsten Grad: 250 GS.
|
||||
@@ -90,7 +98,10 @@
|
||||
@dblclick="startEditProp('spezialisierung', character.spezialisierung)"
|
||||
class="editable-prop"
|
||||
>{{ character.spezialisierung || '-' }}</span>
|
||||
<input v-else v-model="editPropValue" @blur="saveProp('spezialisierung')" @keyup.enter="saveProp('spezialisierung')" @keyup.esc="cancelEditProp" ref="propInput" class="prop-input" />.
|
||||
<select v-else v-model="editPropValue" @blur="saveProp('spezialisierung')" @keyup.enter="saveProp('spezialisierung')" @keyup.esc="cancelEditProp" ref="propInput" class="prop-input" style="width: 300px;">
|
||||
<option value="">-</option>
|
||||
<option v-for="option in getSelectOptions('spezialisierung')" :key="option" :value="option">{{ option }}</option>
|
||||
</select>.
|
||||
</p>
|
||||
<p>
|
||||
Alter:
|
||||
@@ -105,7 +116,9 @@
|
||||
<span v-else-if="character.hand=='links'">Linkshänder</span>
|
||||
<span v-else>Beidhändig</span>
|
||||
</strong>
|
||||
<input v-else v-model="editPropValue" @blur="saveProp('hand')" @keyup.enter="saveProp('hand')" @keyup.esc="cancelEditProp" ref="propInput" class="prop-input" />,
|
||||
<select v-else v-model="editPropValue" @blur="saveProp('hand')" @keyup.enter="saveProp('hand')" @keyup.esc="cancelEditProp" ref="propInput" class="prop-input">
|
||||
<option v-for="option in getSelectOptions('hand')" :key="option" :value="option">{{ option }}</option>
|
||||
</select>,
|
||||
Größe:
|
||||
<span
|
||||
v-if="editingProp !== 'groesse'"
|
||||
@@ -154,7 +167,9 @@
|
||||
@dblclick="startEditProp('glaube', character.glaube)"
|
||||
class="editable-prop"
|
||||
>{{ character.glaube || '-' }}</span>
|
||||
<input v-else v-model="editPropValue" @blur="saveProp('glaube')" @keyup.enter="saveProp('glaube')" @keyup.esc="cancelEditProp" ref="propInput" class="prop-input" />
|
||||
<select v-else v-model="editPropValue" @blur="saveProp('glaube')" @keyup.enter="saveProp('glaube')" @keyup.esc="cancelEditProp" ref="propInput" class="prop-input">
|
||||
<option v-for="option in getSelectOptions('glaube')" :key="option" :value="option">{{ option }}</option>
|
||||
</select>
|
||||
</p>
|
||||
<p>
|
||||
<strong>Merkmale:</strong>
|
||||
@@ -208,6 +223,7 @@ export default {
|
||||
editingProp: null,
|
||||
editPropValue: '',
|
||||
editPropType: 'text',
|
||||
datasheetOptions: null,
|
||||
characterStats: [
|
||||
{ label: 'stats.strength', path: 'eigenschaften.6.value' },
|
||||
{ label: 'stats.dexterity', path: 'eigenschaften.1.value' },
|
||||
@@ -228,6 +244,17 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async loadDatasheetOptions() {
|
||||
if (this.datasheetOptions) return
|
||||
|
||||
try {
|
||||
const response = await API.get(`/api/characters/${this.character.id}/datasheet-options`)
|
||||
this.datasheetOptions = response.data
|
||||
} catch (error) {
|
||||
console.error('Failed to load datasheet options:', error)
|
||||
alert('Fehler beim Laden der Auswahloptionen')
|
||||
}
|
||||
},
|
||||
handleImageUpdate(newImage) {
|
||||
this.$emit('character-updated')
|
||||
},
|
||||
@@ -283,6 +310,13 @@ export default {
|
||||
this.editValue = ''
|
||||
},
|
||||
startEditProp(prop, value, type = 'text') {
|
||||
// Load options if this is a select field
|
||||
const selectFields = ['gender', 'rasse', 'origin', 'social_class', 'glaube', 'hand', 'spezialisierung']
|
||||
if (selectFields.includes(prop)) {
|
||||
this.loadDatasheetOptions()
|
||||
type = 'select'
|
||||
}
|
||||
|
||||
this.editingProp = prop
|
||||
this.editPropValue = value || ''
|
||||
this.editPropType = type
|
||||
@@ -291,7 +325,9 @@ export default {
|
||||
const input = Array.isArray(this.$refs.propInput) ? this.$refs.propInput[0] : this.$refs.propInput
|
||||
if (input) {
|
||||
input.focus()
|
||||
input.select()
|
||||
if (type !== 'select') {
|
||||
input.select()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -331,6 +367,21 @@ export default {
|
||||
this.cancelEditProp()
|
||||
}
|
||||
},
|
||||
getSelectOptions(prop) {
|
||||
if (!this.datasheetOptions) return []
|
||||
|
||||
const optionMap = {
|
||||
'gender': 'gender',
|
||||
'rasse': 'races',
|
||||
'origin': 'origins',
|
||||
'social_class': 'social_classes',
|
||||
'glaube': 'faiths',
|
||||
'hand': 'handedness',
|
||||
'spezialisierung': 'specializations'
|
||||
}
|
||||
|
||||
return this.datasheetOptions[optionMap[prop]] || []
|
||||
},
|
||||
cancelEditProp() {
|
||||
this.editingProp = null
|
||||
this.editPropValue = ''
|
||||
|
||||
Reference in New Issue
Block a user