normalized the caster to return always non-null value and fixed minor ui issues
This commit is contained in:
		
							parent
							
								
									f19b9e3552
								
							
						
					
					
						commit
						994761b728
					
				| 
						 | 
				
			
			@ -144,12 +144,12 @@ func TestRecordsList(t *testing.T) {
 | 
			
		|||
				`"manyrels":[{`,
 | 
			
		||||
				`"manyrels":[]`,
 | 
			
		||||
				`"rel_cascade":"`,
 | 
			
		||||
				`"rel_cascade":null`,
 | 
			
		||||
				`"rel_cascade":""`,
 | 
			
		||||
				`"onerel":{"@collectionId":"3f2888f8-075d-49fe-9d09-ea7e951000dc","@collectionName":"demo",`,
 | 
			
		||||
				`"json":[1,2,3]`,
 | 
			
		||||
				`"select":["a","b"]`,
 | 
			
		||||
				`"select":[]`,
 | 
			
		||||
				`"user":null`,
 | 
			
		||||
				`"user":""`,
 | 
			
		||||
				`"bool":true`,
 | 
			
		||||
				`"number":456`,
 | 
			
		||||
				`"user":"97cc3d3d-6ba2-383f-b42a-7bc84d27410c"`,
 | 
			
		||||
| 
						 | 
				
			
			@ -650,7 +650,8 @@ func TestRecordCreate(t *testing.T) {
 | 
			
		|||
				"onerel": "577bd676-aacb-4072-b7da-99d00ee210a4",
 | 
			
		||||
				"manyrels": ["577bd676-aacb-4072-b7da-99d00ee210a4"],
 | 
			
		||||
				"text": "test123",
 | 
			
		||||
				"bool": "false"
 | 
			
		||||
				"bool": "false",
 | 
			
		||||
				"number": 1
 | 
			
		||||
			}`),
 | 
			
		||||
			RequestHeaders: map[string]string{
 | 
			
		||||
				// test@example.com
 | 
			
		||||
| 
						 | 
				
			
			@ -668,7 +669,8 @@ func TestRecordCreate(t *testing.T) {
 | 
			
		|||
				"onerel":"577bd676-aacb-4072-b7da-99d00ee210a4",
 | 
			
		||||
				"manyrels":["577bd676-aacb-4072-b7da-99d00ee210a4"],
 | 
			
		||||
				"text":"test123",
 | 
			
		||||
				"bool":true
 | 
			
		||||
				"bool":true,
 | 
			
		||||
				"number":1
 | 
			
		||||
			}`),
 | 
			
		||||
			RequestHeaders: map[string]string{
 | 
			
		||||
				// test3@example.com
 | 
			
		||||
| 
						 | 
				
			
			@ -682,6 +684,7 @@ func TestRecordCreate(t *testing.T) {
 | 
			
		|||
				`"manyrels":["577bd676-aacb-4072-b7da-99d00ee210a4"]`,
 | 
			
		||||
				`"text":"test123"`,
 | 
			
		||||
				`"bool":true`,
 | 
			
		||||
				`"number":1`,
 | 
			
		||||
			},
 | 
			
		||||
			ExpectedEvents: map[string]int{
 | 
			
		||||
				"OnRecordBeforeCreateRequest": 1,
 | 
			
		||||
| 
						 | 
				
			
			@ -699,7 +702,8 @@ func TestRecordCreate(t *testing.T) {
 | 
			
		|||
				"onerel": "577bd676-aacb-4072-b7da-99d00ee210a4",
 | 
			
		||||
				"manyrels" :["577bd676-aacb-4072-b7da-99d00ee210a4"],
 | 
			
		||||
				"text": "test123",
 | 
			
		||||
				"bool":false
 | 
			
		||||
				"bool": false,
 | 
			
		||||
				"number": 1
 | 
			
		||||
			}`),
 | 
			
		||||
			RequestHeaders: map[string]string{
 | 
			
		||||
				"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
 | 
			
		||||
| 
						 | 
				
			
			@ -712,6 +716,7 @@ func TestRecordCreate(t *testing.T) {
 | 
			
		|||
				`"manyrels":["577bd676-aacb-4072-b7da-99d00ee210a4"]`,
 | 
			
		||||
				`"text":"test123"`,
 | 
			
		||||
				`"bool":false`,
 | 
			
		||||
				`"number":1`,
 | 
			
		||||
			},
 | 
			
		||||
			ExpectedEvents: map[string]int{
 | 
			
		||||
				"OnRecordBeforeCreateRequest": 1,
 | 
			
		||||
| 
						 | 
				
			
			@ -867,7 +872,8 @@ func TestRecordUpdate(t *testing.T) {
 | 
			
		|||
			Method: http.MethodPatch,
 | 
			
		||||
			Url:    "/api/collections/demo2/records/63c2ab80-84ab-4057-a592-4604a731f78f",
 | 
			
		||||
			Body: strings.NewReader(`{
 | 
			
		||||
				"text":"test_new"
 | 
			
		||||
				"text":"test_new",
 | 
			
		||||
				"number":1
 | 
			
		||||
			}`),
 | 
			
		||||
			RequestHeaders: map[string]string{
 | 
			
		||||
				"Authorization": "Admin eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjJiNGE5N2NjLTNmODMtNGQwMS1hMjZiLTNkNzdiYzg0MmQzYyIsInR5cGUiOiJhZG1pbiIsImV4cCI6MTg3MzQ2Mjc5Mn0.AtRtXR6FHBrCUGkj5OffhmxLbSZaQ4L_Qgw4gfoHyfo",
 | 
			
		||||
| 
						 | 
				
			
			@ -876,6 +882,7 @@ func TestRecordUpdate(t *testing.T) {
 | 
			
		|||
			ExpectedContent: []string{
 | 
			
		||||
				`"id":"63c2ab80-84ab-4057-a592-4604a731f78f"`,
 | 
			
		||||
				`"text":"test_new"`,
 | 
			
		||||
				`"number":1`,
 | 
			
		||||
			},
 | 
			
		||||
			ExpectedEvents: map[string]int{
 | 
			
		||||
				"OnRecordBeforeUpdateRequest": 1,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -167,7 +167,7 @@ func (form *RecordUpsert) LoadData(r *http.Request) error {
 | 
			
		|||
				if len(oldNames) > 0 {
 | 
			
		||||
					form.filesToDelete = append(form.filesToDelete, oldNames...)
 | 
			
		||||
				}
 | 
			
		||||
				form.Data[key] = nil
 | 
			
		||||
				form.Data[key] = ""
 | 
			
		||||
			}
 | 
			
		||||
		} else if options.MaxSelect > 1 {
 | 
			
		||||
			// search for individual file index to delete (eg. "file.0")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -98,8 +98,8 @@ func TestRecordUpsertLoadDataJson(t *testing.T) {
 | 
			
		|||
	if !ok {
 | 
			
		||||
		t.Fatal("Expect onefile field to be set")
 | 
			
		||||
	}
 | 
			
		||||
	if onefile != nil {
 | 
			
		||||
		t.Fatalf("Expect onefile field to be nil, got %v", onefile)
 | 
			
		||||
	if onefile != "" {
 | 
			
		||||
		t.Fatalf("Expect onefile field to be empty string, got %v", onefile)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	manyfiles, ok := form.Data["manyfiles"]
 | 
			
		||||
| 
						 | 
				
			
			@ -166,8 +166,8 @@ func TestRecordUpsertLoadDataMultipart(t *testing.T) {
 | 
			
		|||
	if !ok {
 | 
			
		||||
		t.Fatal("Expect onefile field to be set")
 | 
			
		||||
	}
 | 
			
		||||
	if onefile != nil {
 | 
			
		||||
		t.Fatalf("Expect onefile field to be nil, got %v", onefile)
 | 
			
		||||
	if onefile != "" {
 | 
			
		||||
		t.Fatalf("Expect onefile field to be empty string, got %v", onefile)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	manyfiles, ok := form.Data["manyfiles"]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -240,7 +240,6 @@ func (validator *RecordDataValidator) checkUrlValue(field *schema.SchemaField, v
 | 
			
		|||
 | 
			
		||||
func (validator *RecordDataValidator) checkDateValue(field *schema.SchemaField, value any) error {
 | 
			
		||||
	val, _ := value.(types.DateTime)
 | 
			
		||||
 | 
			
		||||
	if val.IsZero() {
 | 
			
		||||
		if field.Required {
 | 
			
		||||
			return requiredErr
 | 
			
		||||
| 
						 | 
				
			
			@ -268,6 +267,9 @@ func (validator *RecordDataValidator) checkDateValue(field *schema.SchemaField,
 | 
			
		|||
func (validator *RecordDataValidator) checkSelectValue(field *schema.SchemaField, value any) error {
 | 
			
		||||
	normalizedVal := list.ToUniqueStringSlice(value)
 | 
			
		||||
	if len(normalizedVal) == 0 {
 | 
			
		||||
		if field.Required {
 | 
			
		||||
			return requiredErr
 | 
			
		||||
		}
 | 
			
		||||
		return nil // nothing to check
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -302,13 +304,9 @@ func (validator *RecordDataValidator) checkJsonValue(field *schema.SchemaField,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (validator *RecordDataValidator) checkFileValue(field *schema.SchemaField, value any) error {
 | 
			
		||||
	// normalize value access
 | 
			
		||||
	var names []string
 | 
			
		||||
	switch v := value.(type) {
 | 
			
		||||
	case []string:
 | 
			
		||||
		names = v
 | 
			
		||||
	case string:
 | 
			
		||||
		names = []string{v}
 | 
			
		||||
	names := list.ToUniqueStringSlice(value)
 | 
			
		||||
	if len(names) == 0 && field.Required {
 | 
			
		||||
		return requiredErr
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	options, _ := field.Options.(*schema.FileOptions)
 | 
			
		||||
| 
						 | 
				
			
			@ -343,16 +341,11 @@ func (validator *RecordDataValidator) checkFileValue(field *schema.SchemaField,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (validator *RecordDataValidator) checkRelationValue(field *schema.SchemaField, value any) error {
 | 
			
		||||
	// normalize value access
 | 
			
		||||
	var ids []string
 | 
			
		||||
	switch v := value.(type) {
 | 
			
		||||
	case []string:
 | 
			
		||||
		ids = v
 | 
			
		||||
	case string:
 | 
			
		||||
		ids = []string{v}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ids := list.ToUniqueStringSlice(value)
 | 
			
		||||
	if len(ids) == 0 {
 | 
			
		||||
		if field.Required {
 | 
			
		||||
			return requiredErr
 | 
			
		||||
		}
 | 
			
		||||
		return nil // nothing to check
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -383,16 +376,11 @@ func (validator *RecordDataValidator) checkRelationValue(field *schema.SchemaFie
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func (validator *RecordDataValidator) checkUserValue(field *schema.SchemaField, value any) error {
 | 
			
		||||
	// normalize value access
 | 
			
		||||
	var ids []string
 | 
			
		||||
	switch v := value.(type) {
 | 
			
		||||
	case []string:
 | 
			
		||||
		ids = v
 | 
			
		||||
	case string:
 | 
			
		||||
		ids = []string{v}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ids := list.ToUniqueStringSlice(value)
 | 
			
		||||
	if len(ids) == 0 {
 | 
			
		||||
		if field.Required {
 | 
			
		||||
			return requiredErr
 | 
			
		||||
		}
 | 
			
		||||
		return nil // nothing to check
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -89,7 +89,7 @@ func TestRecordDataValidatorValidateText(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	scenarios := []testDataFieldScenario{
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint",
 | 
			
		||||
			"(text) check required constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": nil,
 | 
			
		||||
				"field2": nil,
 | 
			
		||||
| 
						 | 
				
			
			@ -99,7 +99,7 @@ func TestRecordDataValidatorValidateText(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check unique constraint",
 | 
			
		||||
			"(text) check unique constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "test",
 | 
			
		||||
				"field2": "test",
 | 
			
		||||
| 
						 | 
				
			
			@ -109,7 +109,7 @@ func TestRecordDataValidatorValidateText(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check min constraint",
 | 
			
		||||
			"(text) check min constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "test",
 | 
			
		||||
				"field2": "test",
 | 
			
		||||
| 
						 | 
				
			
			@ -119,7 +119,7 @@ func TestRecordDataValidatorValidateText(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check max constraint",
 | 
			
		||||
			"(text) check max constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "test",
 | 
			
		||||
				"field2": "test",
 | 
			
		||||
| 
						 | 
				
			
			@ -129,7 +129,7 @@ func TestRecordDataValidatorValidateText(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check pattern constraint",
 | 
			
		||||
			"(text) check pattern constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": nil,
 | 
			
		||||
				"field2": "test",
 | 
			
		||||
| 
						 | 
				
			
			@ -139,7 +139,7 @@ func TestRecordDataValidatorValidateText(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data (only required)",
 | 
			
		||||
			"(text) valid data (only required)",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field2": "test",
 | 
			
		||||
			},
 | 
			
		||||
| 
						 | 
				
			
			@ -147,7 +147,7 @@ func TestRecordDataValidatorValidateText(t *testing.T) {
 | 
			
		|||
			[]string{},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data (all)",
 | 
			
		||||
			"(text) valid data (all)",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "test",
 | 
			
		||||
				"field2": 12345, // test value cast
 | 
			
		||||
| 
						 | 
				
			
			@ -168,7 +168,7 @@ func TestRecordDataValidatorValidateNumber(t *testing.T) {
 | 
			
		|||
	// create new test collection
 | 
			
		||||
	collection := &models.Collection{}
 | 
			
		||||
	collection.Name = "validate_test"
 | 
			
		||||
	min := 1.0
 | 
			
		||||
	min := 0.0
 | 
			
		||||
	max := 150.0
 | 
			
		||||
	collection.Schema = schema.NewSchema(
 | 
			
		||||
		&schema.SchemaField{
 | 
			
		||||
| 
						 | 
				
			
			@ -205,7 +205,7 @@ func TestRecordDataValidatorValidateNumber(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	scenarios := []testDataFieldScenario{
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint",
 | 
			
		||||
			"(number) check required constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": nil,
 | 
			
		||||
				"field2": nil,
 | 
			
		||||
| 
						 | 
				
			
			@ -215,17 +215,17 @@ func TestRecordDataValidatorValidateNumber(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint + casting",
 | 
			
		||||
			"(number) check required constraint + casting",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "invalid",
 | 
			
		||||
				"field2": "invalid",
 | 
			
		||||
				"field3": "invalid",
 | 
			
		||||
			},
 | 
			
		||||
			nil,
 | 
			
		||||
			[]string{"field2", "field3"},
 | 
			
		||||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check unique constraint",
 | 
			
		||||
			"(number) check unique constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": 123,
 | 
			
		||||
				"field2": 123,
 | 
			
		||||
| 
						 | 
				
			
			@ -235,7 +235,7 @@ func TestRecordDataValidatorValidateNumber(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check min constraint",
 | 
			
		||||
			"(number) check min constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": 0.5,
 | 
			
		||||
				"field2": 1,
 | 
			
		||||
| 
						 | 
				
			
			@ -245,7 +245,7 @@ func TestRecordDataValidatorValidateNumber(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check max constraint",
 | 
			
		||||
			"(number) check max constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": nil,
 | 
			
		||||
				"field2": max,
 | 
			
		||||
| 
						 | 
				
			
			@ -255,7 +255,7 @@ func TestRecordDataValidatorValidateNumber(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data (only required)",
 | 
			
		||||
			"(number) valid data (only required)",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field2": 1,
 | 
			
		||||
			},
 | 
			
		||||
| 
						 | 
				
			
			@ -263,7 +263,7 @@ func TestRecordDataValidatorValidateNumber(t *testing.T) {
 | 
			
		|||
			[]string{},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data (all)",
 | 
			
		||||
			"(number) valid data (all)",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": nil,
 | 
			
		||||
				"field2": 123, // test value cast
 | 
			
		||||
| 
						 | 
				
			
			@ -316,7 +316,7 @@ func TestRecordDataValidatorValidateBool(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	scenarios := []testDataFieldScenario{
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint",
 | 
			
		||||
			"(bool) check required constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": nil,
 | 
			
		||||
				"field2": nil,
 | 
			
		||||
| 
						 | 
				
			
			@ -326,7 +326,7 @@ func TestRecordDataValidatorValidateBool(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint + casting",
 | 
			
		||||
			"(bool) check required constraint + casting",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "invalid",
 | 
			
		||||
				"field2": "invalid",
 | 
			
		||||
| 
						 | 
				
			
			@ -336,7 +336,7 @@ func TestRecordDataValidatorValidateBool(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check unique constraint",
 | 
			
		||||
			"(bool) check unique constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": true,
 | 
			
		||||
				"field2": true,
 | 
			
		||||
| 
						 | 
				
			
			@ -346,7 +346,7 @@ func TestRecordDataValidatorValidateBool(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data (only required)",
 | 
			
		||||
			"(bool) valid data (only required)",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field2": 1,
 | 
			
		||||
			},
 | 
			
		||||
| 
						 | 
				
			
			@ -354,7 +354,7 @@ func TestRecordDataValidatorValidateBool(t *testing.T) {
 | 
			
		|||
			[]string{},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data (all)",
 | 
			
		||||
			"(bool) valid data (all)",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": false,
 | 
			
		||||
				"field2": true,
 | 
			
		||||
| 
						 | 
				
			
			@ -412,7 +412,7 @@ func TestRecordDataValidatorValidateEmail(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	scenarios := []testDataFieldScenario{
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint",
 | 
			
		||||
			"(email) check required constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": nil,
 | 
			
		||||
				"field2": nil,
 | 
			
		||||
| 
						 | 
				
			
			@ -422,7 +422,7 @@ func TestRecordDataValidatorValidateEmail(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check email format validator",
 | 
			
		||||
			"(email) check email format validator",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "test",
 | 
			
		||||
				"field2": "test.com",
 | 
			
		||||
| 
						 | 
				
			
			@ -432,7 +432,7 @@ func TestRecordDataValidatorValidateEmail(t *testing.T) {
 | 
			
		|||
			[]string{"field1", "field2", "field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check unique constraint",
 | 
			
		||||
			"(email) check unique constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "test@example.com",
 | 
			
		||||
				"field2": "test@test.com",
 | 
			
		||||
| 
						 | 
				
			
			@ -442,7 +442,7 @@ func TestRecordDataValidatorValidateEmail(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check ExceptDomains constraint",
 | 
			
		||||
			"(email) check ExceptDomains constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "test@example.com",
 | 
			
		||||
				"field2": "test@example.com",
 | 
			
		||||
| 
						 | 
				
			
			@ -452,7 +452,7 @@ func TestRecordDataValidatorValidateEmail(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check OnlyDomains constraint",
 | 
			
		||||
			"(email) check OnlyDomains constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "test@test.com",
 | 
			
		||||
				"field2": "test@test.com",
 | 
			
		||||
| 
						 | 
				
			
			@ -462,7 +462,7 @@ func TestRecordDataValidatorValidateEmail(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data (only required)",
 | 
			
		||||
			"(email) valid data (only required)",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field2": "test@test.com",
 | 
			
		||||
			},
 | 
			
		||||
| 
						 | 
				
			
			@ -470,7 +470,7 @@ func TestRecordDataValidatorValidateEmail(t *testing.T) {
 | 
			
		|||
			[]string{},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data (all)",
 | 
			
		||||
			"(email) valid data (all)",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "123@example.com",
 | 
			
		||||
				"field2": "test@test.com",
 | 
			
		||||
| 
						 | 
				
			
			@ -528,7 +528,7 @@ func TestRecordDataValidatorValidateUrl(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	scenarios := []testDataFieldScenario{
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint",
 | 
			
		||||
			"(url) check required constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": nil,
 | 
			
		||||
				"field2": nil,
 | 
			
		||||
| 
						 | 
				
			
			@ -538,7 +538,7 @@ func TestRecordDataValidatorValidateUrl(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check url format validator",
 | 
			
		||||
			"(url) check url format validator",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "/abc",
 | 
			
		||||
				"field2": "test.com", // valid
 | 
			
		||||
| 
						 | 
				
			
			@ -548,7 +548,7 @@ func TestRecordDataValidatorValidateUrl(t *testing.T) {
 | 
			
		|||
			[]string{"field1", "field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check unique constraint",
 | 
			
		||||
			"(url) check unique constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "http://example.com",
 | 
			
		||||
				"field2": "http://test.com",
 | 
			
		||||
| 
						 | 
				
			
			@ -558,7 +558,7 @@ func TestRecordDataValidatorValidateUrl(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check ExceptDomains constraint",
 | 
			
		||||
			"(url) check ExceptDomains constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "http://example.com",
 | 
			
		||||
				"field2": "http://example.com",
 | 
			
		||||
| 
						 | 
				
			
			@ -568,7 +568,7 @@ func TestRecordDataValidatorValidateUrl(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check OnlyDomains constraint",
 | 
			
		||||
			"(url) check OnlyDomains constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "http://test.com/abc",
 | 
			
		||||
				"field2": "http://test.com/abc",
 | 
			
		||||
| 
						 | 
				
			
			@ -578,7 +578,7 @@ func TestRecordDataValidatorValidateUrl(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check subdomains constraint",
 | 
			
		||||
			"(url) check subdomains constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "http://test.test.com",
 | 
			
		||||
				"field2": "http://test.example.com",
 | 
			
		||||
| 
						 | 
				
			
			@ -588,7 +588,7 @@ func TestRecordDataValidatorValidateUrl(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data (only required)",
 | 
			
		||||
			"(url) valid data (only required)",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field2": "http://sub.test.com/abc",
 | 
			
		||||
			},
 | 
			
		||||
| 
						 | 
				
			
			@ -596,7 +596,7 @@ func TestRecordDataValidatorValidateUrl(t *testing.T) {
 | 
			
		|||
			[]string{},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data (all)",
 | 
			
		||||
			"(url) valid data (all)",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "http://example.com/123",
 | 
			
		||||
				"field2": "http://test.com/",
 | 
			
		||||
| 
						 | 
				
			
			@ -656,7 +656,7 @@ func TestRecordDataValidatorValidateDate(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	scenarios := []testDataFieldScenario{
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint",
 | 
			
		||||
			"(date) check required constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": nil,
 | 
			
		||||
				"field2": nil,
 | 
			
		||||
| 
						 | 
				
			
			@ -666,7 +666,7 @@ func TestRecordDataValidatorValidateDate(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint + cast",
 | 
			
		||||
			"(date) check required constraint + cast",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "invalid",
 | 
			
		||||
				"field2": "invalid",
 | 
			
		||||
| 
						 | 
				
			
			@ -676,7 +676,7 @@ func TestRecordDataValidatorValidateDate(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint + zero datetime",
 | 
			
		||||
			"(date) check required constraint + zero datetime",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "January 1, year 1, 00:00:00 UTC",
 | 
			
		||||
				"field2": "0001-01-01 00:00:00",
 | 
			
		||||
| 
						 | 
				
			
			@ -686,7 +686,7 @@ func TestRecordDataValidatorValidateDate(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check unique constraint",
 | 
			
		||||
			"(date) check unique constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "2029-01-01 01:01:01.123",
 | 
			
		||||
				"field2": "2029-01-01 01:01:01.123",
 | 
			
		||||
| 
						 | 
				
			
			@ -696,7 +696,7 @@ func TestRecordDataValidatorValidateDate(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check min date constraint",
 | 
			
		||||
			"(date) check min date constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "2021-01-01 01:01:01",
 | 
			
		||||
				"field2": "2021-01-01 01:01:01",
 | 
			
		||||
| 
						 | 
				
			
			@ -706,7 +706,7 @@ func TestRecordDataValidatorValidateDate(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check max date constraint",
 | 
			
		||||
			"(date) check max date constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "2030-02-01 01:01:01",
 | 
			
		||||
				"field2": "2030-02-01 01:01:01",
 | 
			
		||||
| 
						 | 
				
			
			@ -716,7 +716,7 @@ func TestRecordDataValidatorValidateDate(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data (only required)",
 | 
			
		||||
			"(date) valid data (only required)",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field2": "2029-01-01 01:01:01",
 | 
			
		||||
			},
 | 
			
		||||
| 
						 | 
				
			
			@ -724,7 +724,7 @@ func TestRecordDataValidatorValidateDate(t *testing.T) {
 | 
			
		|||
			[]string{},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data (all)",
 | 
			
		||||
			"(date) valid data (all)",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "2029-01-01 01:01:01.000",
 | 
			
		||||
				"field2": "2029-01-01 01:01:01",
 | 
			
		||||
| 
						 | 
				
			
			@ -788,7 +788,7 @@ func TestRecordDataValidatorValidateSelect(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	scenarios := []testDataFieldScenario{
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint",
 | 
			
		||||
			"(select) check required constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": nil,
 | 
			
		||||
				"field2": nil,
 | 
			
		||||
| 
						 | 
				
			
			@ -798,7 +798,7 @@ func TestRecordDataValidatorValidateSelect(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint - empty values",
 | 
			
		||||
			"(select) check required constraint - empty values",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "",
 | 
			
		||||
				"field2": "",
 | 
			
		||||
| 
						 | 
				
			
			@ -808,7 +808,7 @@ func TestRecordDataValidatorValidateSelect(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint - multiple select cast",
 | 
			
		||||
			"(select) check required constraint - multiple select cast",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "a",
 | 
			
		||||
				"field2": "a",
 | 
			
		||||
| 
						 | 
				
			
			@ -818,7 +818,7 @@ func TestRecordDataValidatorValidateSelect(t *testing.T) {
 | 
			
		|||
			[]string{},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check unique constraint",
 | 
			
		||||
			"(select) check unique constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "a",
 | 
			
		||||
				"field2": "b",
 | 
			
		||||
| 
						 | 
				
			
			@ -828,7 +828,7 @@ func TestRecordDataValidatorValidateSelect(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check unique constraint - same elements but different order",
 | 
			
		||||
			"(select) check unique constraint - same elements but different order",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "a",
 | 
			
		||||
				"field2": "b",
 | 
			
		||||
| 
						 | 
				
			
			@ -838,7 +838,7 @@ func TestRecordDataValidatorValidateSelect(t *testing.T) {
 | 
			
		|||
			[]string{},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check Values constraint",
 | 
			
		||||
			"(select) check Values constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": 1,
 | 
			
		||||
				"field2": "d",
 | 
			
		||||
| 
						 | 
				
			
			@ -848,7 +848,7 @@ func TestRecordDataValidatorValidateSelect(t *testing.T) {
 | 
			
		|||
			[]string{"field2", "field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check MaxSelect constraint",
 | 
			
		||||
			"(select) check MaxSelect constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": []string{"a", "b"}, // this will be normalized to a single string value
 | 
			
		||||
				"field2": []string{"a", "b", "c"},
 | 
			
		||||
| 
						 | 
				
			
			@ -858,7 +858,7 @@ func TestRecordDataValidatorValidateSelect(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data - only required fields",
 | 
			
		||||
			"(select) valid data - only required fields",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field2": []string{"a", "b"},
 | 
			
		||||
			},
 | 
			
		||||
| 
						 | 
				
			
			@ -866,7 +866,7 @@ func TestRecordDataValidatorValidateSelect(t *testing.T) {
 | 
			
		|||
			[]string{},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data - all fields with normalizations",
 | 
			
		||||
			"(select) valid data - all fields with normalizations",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "a",
 | 
			
		||||
				"field2": []string{"a", "b", "b"}, // will be collapsed
 | 
			
		||||
| 
						 | 
				
			
			@ -918,7 +918,7 @@ func TestRecordDataValidatorValidateJson(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	scenarios := []testDataFieldScenario{
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint - nil",
 | 
			
		||||
			"(json) check required constraint - nil",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": nil,
 | 
			
		||||
				"field2": nil,
 | 
			
		||||
| 
						 | 
				
			
			@ -928,7 +928,7 @@ func TestRecordDataValidatorValidateJson(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint - zero string",
 | 
			
		||||
			"(json) check required constraint - zero string",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": "",
 | 
			
		||||
				"field2": "",
 | 
			
		||||
| 
						 | 
				
			
			@ -938,7 +938,7 @@ func TestRecordDataValidatorValidateJson(t *testing.T) {
 | 
			
		|||
			[]string{"field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint - zero number",
 | 
			
		||||
			"(json) check required constraint - zero number",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": 0,
 | 
			
		||||
				"field2": 0,
 | 
			
		||||
| 
						 | 
				
			
			@ -948,7 +948,7 @@ func TestRecordDataValidatorValidateJson(t *testing.T) {
 | 
			
		|||
			[]string{},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint - zero slice",
 | 
			
		||||
			"(json) check required constraint - zero slice",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": []string{},
 | 
			
		||||
				"field2": []string{},
 | 
			
		||||
| 
						 | 
				
			
			@ -958,7 +958,7 @@ func TestRecordDataValidatorValidateJson(t *testing.T) {
 | 
			
		|||
			[]string{},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check required constraint - zero map",
 | 
			
		||||
			"(json) check required constraint - zero map",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": map[string]string{},
 | 
			
		||||
				"field2": map[string]string{},
 | 
			
		||||
| 
						 | 
				
			
			@ -968,7 +968,7 @@ func TestRecordDataValidatorValidateJson(t *testing.T) {
 | 
			
		|||
			[]string{},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check unique constraint",
 | 
			
		||||
			"(json) check unique constraint",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": `{"test":123}`,
 | 
			
		||||
				"field2": `{"test":123}`,
 | 
			
		||||
| 
						 | 
				
			
			@ -978,7 +978,7 @@ func TestRecordDataValidatorValidateJson(t *testing.T) {
 | 
			
		|||
			[]string{"field3"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"check json text validator",
 | 
			
		||||
			"(json) check json text validator",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": `[1, 2, 3`,
 | 
			
		||||
				"field2": `invalid`,
 | 
			
		||||
| 
						 | 
				
			
			@ -988,7 +988,7 @@ func TestRecordDataValidatorValidateJson(t *testing.T) {
 | 
			
		|||
			[]string{"field1", "field2"},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data - only required fields",
 | 
			
		||||
			"(json) valid data - only required fields",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field2": `{"test":123}`,
 | 
			
		||||
			},
 | 
			
		||||
| 
						 | 
				
			
			@ -996,7 +996,7 @@ func TestRecordDataValidatorValidateJson(t *testing.T) {
 | 
			
		|||
			[]string{},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			"valid data - all fields with normalizations",
 | 
			
		||||
			"(json) valid data - all fields with normalizations",
 | 
			
		||||
			map[string]any{
 | 
			
		||||
				"field1": []string{"a", "b", "c"},
 | 
			
		||||
				"field2": 123,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -118,7 +118,7 @@ func TestNewRecordFromNullStringMap(t *testing.T) {
 | 
			
		|||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	expected := `{"@collectionId":"","@collectionName":"test","created":"2022-01-01 10:00:00.123","field1":"test","field2":null,"field3":true,"field4":123.123,"field5":"test1","field6":["test"],"id":"c23eb053-d07e-4fbe-86b3-b8ac31982e9a","updated":"2022-01-01 10:00:00.456"}`
 | 
			
		||||
	expected := `{"@collectionId":"","@collectionName":"test","created":"2022-01-01 10:00:00.123","field1":"test","field2":"","field3":true,"field4":123.123,"field5":"test1","field6":["test"],"id":"c23eb053-d07e-4fbe-86b3-b8ac31982e9a","updated":"2022-01-01 10:00:00.456"}`
 | 
			
		||||
 | 
			
		||||
	if string(encoded) != expected {
 | 
			
		||||
		t.Fatalf("Expected %v, got \n%v", expected, string(encoded))
 | 
			
		||||
| 
						 | 
				
			
			@ -185,10 +185,10 @@ func TestNewRecordsFromNullStringMaps(t *testing.T) {
 | 
			
		|||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	expected := `[{"@collectionId":"","@collectionName":"test","created":"2022-01-01 10:00:00.123","field1":"test1","field2":null,"id":"11111111-d07e-4fbe-86b3-b8ac31982e9a","updated":"2022-01-01 10:00:00.456"},{"@collectionId":"","@collectionName":"test","created":"","field1":"test2","field2":123,"id":"22222222-d07e-4fbe-86b3-b8ac31982e9a","updated":""}]`
 | 
			
		||||
	expected := `[{"@collectionId":"","@collectionName":"test","created":"2022-01-01 10:00:00.123","field1":"test1","field2":0,"id":"11111111-d07e-4fbe-86b3-b8ac31982e9a","updated":"2022-01-01 10:00:00.456"},{"@collectionId":"","@collectionName":"test","created":"","field1":"test2","field2":123,"id":"22222222-d07e-4fbe-86b3-b8ac31982e9a","updated":""}]`
 | 
			
		||||
 | 
			
		||||
	if string(encoded) != expected {
 | 
			
		||||
		t.Fatalf("Expected %v, got \n%v", expected, string(encoded))
 | 
			
		||||
		t.Fatalf("Expected \n%v, got \n%v", expected, string(encoded))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -218,31 +218,19 @@ func (f *SchemaField) PrepareValue(value any) any {
 | 
			
		|||
	f.InitOptions()
 | 
			
		||||
 | 
			
		||||
	switch f.Type {
 | 
			
		||||
	case FieldTypeText, FieldTypeEmail, FieldTypeUrl: // string
 | 
			
		||||
		if value == nil {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	case FieldTypeText, FieldTypeEmail, FieldTypeUrl:
 | 
			
		||||
		return cast.ToString(value)
 | 
			
		||||
	case FieldTypeJson: // string
 | 
			
		||||
		if value == nil {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	case FieldTypeJson:
 | 
			
		||||
		val, _ := types.ParseJsonRaw(value)
 | 
			
		||||
		return val
 | 
			
		||||
	case FieldTypeNumber: // nil, int or float
 | 
			
		||||
		if value == nil {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	case FieldTypeNumber:
 | 
			
		||||
		return cast.ToFloat64(value)
 | 
			
		||||
	case FieldTypeBool: // bool
 | 
			
		||||
	case FieldTypeBool:
 | 
			
		||||
		return cast.ToBool(value)
 | 
			
		||||
	case FieldTypeDate: // string, DateTime or time.Time
 | 
			
		||||
		if value == nil {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	case FieldTypeDate:
 | 
			
		||||
		val, _ := types.ParseDateTime(value)
 | 
			
		||||
		return val
 | 
			
		||||
	case FieldTypeSelect: // nil, string or slice of strings
 | 
			
		||||
	case FieldTypeSelect:
 | 
			
		||||
		val := list.ToUniqueStringSlice(value)
 | 
			
		||||
 | 
			
		||||
		options, _ := f.Options.(*SelectOptions)
 | 
			
		||||
| 
						 | 
				
			
			@ -250,11 +238,11 @@ func (f *SchemaField) PrepareValue(value any) any {
 | 
			
		|||
			if len(val) > 0 {
 | 
			
		||||
				return val[0]
 | 
			
		||||
			}
 | 
			
		||||
			return nil
 | 
			
		||||
			return ""
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return val
 | 
			
		||||
	case FieldTypeFile: // nil, string or slice of strings
 | 
			
		||||
	case FieldTypeFile:
 | 
			
		||||
		val := list.ToUniqueStringSlice(value)
 | 
			
		||||
 | 
			
		||||
		options, _ := f.Options.(*FileOptions)
 | 
			
		||||
| 
						 | 
				
			
			@ -262,11 +250,11 @@ func (f *SchemaField) PrepareValue(value any) any {
 | 
			
		|||
			if len(val) > 0 {
 | 
			
		||||
				return val[0]
 | 
			
		||||
			}
 | 
			
		||||
			return nil
 | 
			
		||||
			return ""
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return val
 | 
			
		||||
	case FieldTypeRelation: // nil, string or slice of strings
 | 
			
		||||
	case FieldTypeRelation:
 | 
			
		||||
		ids := list.ToUniqueStringSlice(value)
 | 
			
		||||
 | 
			
		||||
		options, _ := f.Options.(*RelationOptions)
 | 
			
		||||
| 
						 | 
				
			
			@ -274,11 +262,11 @@ func (f *SchemaField) PrepareValue(value any) any {
 | 
			
		|||
			if len(ids) > 0 {
 | 
			
		||||
				return ids[0]
 | 
			
		||||
			}
 | 
			
		||||
			return nil
 | 
			
		||||
			return ""
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return ids
 | 
			
		||||
	case FieldTypeUser: // nil, string or slice of strings
 | 
			
		||||
	case FieldTypeUser:
 | 
			
		||||
		ids := list.ToUniqueStringSlice(value)
 | 
			
		||||
 | 
			
		||||
		options, _ := f.Options.(*UserOptions)
 | 
			
		||||
| 
						 | 
				
			
			@ -286,7 +274,7 @@ func (f *SchemaField) PrepareValue(value any) any {
 | 
			
		|||
			if len(ids) > 0 {
 | 
			
		||||
				return ids[0]
 | 
			
		||||
			}
 | 
			
		||||
			return nil
 | 
			
		||||
			return ""
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return ids
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -498,19 +498,22 @@ func TestSchemaFieldPrepareValue(t *testing.T) {
 | 
			
		|||
		{schema.SchemaField{Type: "unknown"}, []int{1, 2, 1}, "[1,2,1]"},
 | 
			
		||||
 | 
			
		||||
		// text
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeText}, nil, `null`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeText}, nil, `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeText}, "", `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeText}, []int{1, 2}, `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeText}, "test", `"test"`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeText}, 123, `"123"`},
 | 
			
		||||
 | 
			
		||||
		// email
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeEmail}, nil, `null`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeEmail}, nil, `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeEmail}, "", `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeEmail}, []int{1, 2}, `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeEmail}, "test", `"test"`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeEmail}, 123, `"123"`},
 | 
			
		||||
 | 
			
		||||
		// url
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeUrl}, nil, `null`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeUrl}, nil, `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeUrl}, "", `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeUrl}, []int{1, 2}, `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeUrl}, "test", `"test"`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeUrl}, 123, `"123"`},
 | 
			
		||||
| 
						 | 
				
			
			@ -523,7 +526,9 @@ func TestSchemaFieldPrepareValue(t *testing.T) {
 | 
			
		|||
		{schema.SchemaField{Type: schema.FieldTypeJson}, []int{1, 2, 1}, `[1,2,1]`},
 | 
			
		||||
 | 
			
		||||
		// number
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeNumber}, nil, "null"},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeNumber}, nil, "0"},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeNumber}, "", "0"},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeNumber}, "test", "0"},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeNumber}, 1, "1"},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeNumber}, 1.5, "1.5"},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeNumber}, "1.5", "1.5"},
 | 
			
		||||
| 
						 | 
				
			
			@ -533,22 +538,24 @@ func TestSchemaFieldPrepareValue(t *testing.T) {
 | 
			
		|||
		{schema.SchemaField{Type: schema.FieldTypeBool}, 1, "true"},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeBool}, 0, "false"},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeBool}, "", "false"},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeBool}, "test", "false"},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeBool}, "false", "false"},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeBool}, "true", "true"},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeBool}, false, "false"},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeBool}, true, "true"},
 | 
			
		||||
 | 
			
		||||
		// date
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeDate}, nil, "null"},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeDate}, nil, `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeDate}, "", `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeDate}, "test", `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeDate}, 1641024040, `"2022-01-01 08:00:40.000"`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeDate}, "2022-01-01 11:27:10.123", `"2022-01-01 11:27:10.123"`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeDate}, types.DateTime{}, `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeDate}, time.Time{}, `""`},
 | 
			
		||||
 | 
			
		||||
		// select (single)
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeSelect}, nil, `null`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeSelect}, "", `null`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeSelect}, nil, `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeSelect}, "", `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeSelect}, 123, `"123"`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeSelect}, "test", `"test"`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeSelect}, []string{"test1", "test2"}, `"test1"`},
 | 
			
		||||
| 
						 | 
				
			
			@ -624,8 +631,8 @@ func TestSchemaFieldPrepareValue(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		// file (single)
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeFile}, nil, `null`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeFile}, "", `null`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeFile}, nil, `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeFile}, "", `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeFile}, 123, `"123"`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeFile}, "test", `"test"`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeFile}, []string{"test1", "test2"}, `"test1"`},
 | 
			
		||||
| 
						 | 
				
			
			@ -690,8 +697,8 @@ func TestSchemaFieldPrepareValue(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		// relation (single)
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeRelation}, nil, `null`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeRelation}, "", `null`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeRelation}, nil, `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeRelation}, "", `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeRelation}, 123, `"123"`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeRelation}, "abc", `"abc"`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeRelation}, "1ba88b4f-e9da-42f0-9764-9a55c953e724", `"1ba88b4f-e9da-42f0-9764-9a55c953e724"`},
 | 
			
		||||
| 
						 | 
				
			
			@ -761,8 +768,8 @@ func TestSchemaFieldPrepareValue(t *testing.T) {
 | 
			
		|||
		},
 | 
			
		||||
 | 
			
		||||
		// user (single)
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeUser}, nil, `null`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeUser}, "", `null`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeUser}, nil, `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeUser}, "", `""`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeUser}, 123, `"123"`},
 | 
			
		||||
		{schema.SchemaField{Type: schema.FieldTypeUser}, "1ba88b4f-e9da-42f0-9764-9a55c953e724", `"1ba88b4f-e9da-42f0-9764-9a55c953e724"`},
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -1,2 +1,2 @@
 | 
			
		|||
import{S as E,i as G,s as I,F as K,c as F,m as B,t as H,a as N,d as T,C as M,w as q,e as c,f as u,g as b,h as _,x as O,o as w,q as J,b as k,r as L,u as h,v as Q,j as U,l as V,A as X,p as W,B as Y,D as Z,z as S}from"./index.1a8a9cbf.js";function y(f){let e,o,s;return{c(){e=q("for "),o=c("strong"),s=q(f[3]),u(o,"class","txt-nowrap")},m(l,t){b(l,e,t),b(l,o,t),_(o,s)},p(l,t){t&8&&O(s,l[3])},d(l){l&&w(e),l&&w(o)}}}function x(f){let e,o,s,l,t,r,p,d;return{c(){e=c("label"),o=q("New password"),l=k(),t=c("input"),u(e,"for",s=f[8]),u(t,"type","password"),u(t,"id",r=f[8]),t.required=!0,t.autofocus=!0},m(n,i){b(n,e,i),_(e,o),b(n,l,i),b(n,t,i),S(t,f[0]),t.focus(),p||(d=h(t,"input",f[6]),p=!0)},p(n,i){i&256&&s!==(s=n[8])&&u(e,"for",s),i&256&&r!==(r=n[8])&&u(t,"id",r),i&1&&t.value!==n[0]&&S(t,n[0])},d(n){n&&w(e),n&&w(l),n&&w(t),p=!1,d()}}}function ee(f){let e,o,s,l,t,r,p,d;return{c(){e=c("label"),o=q("New password confirm"),l=k(),t=c("input"),u(e,"for",s=f[8]),u(t,"type","password"),u(t,"id",r=f[8]),t.required=!0},m(n,i){b(n,e,i),_(e,o),b(n,l,i),b(n,t,i),S(t,f[1]),p||(d=h(t,"input",f[7]),p=!0)},p(n,i){i&256&&s!==(s=n[8])&&u(e,"for",s),i&256&&r!==(r=n[8])&&u(t,"id",r),i&2&&t.value!==n[1]&&S(t,n[1])},d(n){n&&w(e),n&&w(l),n&&w(t),p=!1,d()}}}function te(f){let e,o,s,l,t,r,p,d,n,i,g,R,C,v,P,A,j,m=f[3]&&y(f);return r=new J({props:{class:"form-field required",name:"password",$$slots:{default:[x,({uniqueId:a})=>({8:a}),({uniqueId:a})=>a?256:0]},$$scope:{ctx:f}}}),d=new J({props:{class:"form-field required",name:"passwordConfirm",$$slots:{default:[ee,({uniqueId:a})=>({8:a}),({uniqueId:a})=>a?256:0]},$$scope:{ctx:f}}}),{c(){e=c("form"),o=c("div"),s=c("h4"),l=q(`Reset your admin password
 | 
			
		||||
                `),m&&m.c(),t=k(),F(r.$$.fragment),p=k(),F(d.$$.fragment),n=k(),i=c("button"),g=c("span"),g.textContent="Set new password",R=k(),C=c("div"),v=c("a"),v.textContent="Back to login",u(s,"class","m-b-xs"),u(o,"class","content txt-center m-b-sm"),u(g,"class","txt"),u(i,"type","submit"),u(i,"class","btn btn-lg btn-block"),i.disabled=f[2],L(i,"btn-loading",f[2]),u(e,"class","m-b-base"),u(v,"href","/login"),u(v,"class","link-hint"),u(C,"class","content txt-center")},m(a,$){b(a,e,$),_(e,o),_(o,s),_(s,l),m&&m.m(s,null),_(e,t),B(r,e,null),_(e,p),B(d,e,null),_(e,n),_(e,i),_(i,g),b(a,R,$),b(a,C,$),_(C,v),P=!0,A||(j=[h(e,"submit",Q(f[4])),U(V.call(null,v))],A=!0)},p(a,$){a[3]?m?m.p(a,$):(m=y(a),m.c(),m.m(s,null)):m&&(m.d(1),m=null);const z={};$&769&&(z.$$scope={dirty:$,ctx:a}),r.$set(z);const D={};$&770&&(D.$$scope={dirty:$,ctx:a}),d.$set(D),(!P||$&4)&&(i.disabled=a[2]),$&4&&L(i,"btn-loading",a[2])},i(a){P||(H(r.$$.fragment,a),H(d.$$.fragment,a),P=!0)},o(a){N(r.$$.fragment,a),N(d.$$.fragment,a),P=!1},d(a){a&&w(e),m&&m.d(),T(r),T(d),a&&w(R),a&&w(C),A=!1,X(j)}}}function se(f){let e,o;return e=new K({props:{$$slots:{default:[te]},$$scope:{ctx:f}}}),{c(){F(e.$$.fragment)},m(s,l){B(e,s,l),o=!0},p(s,[l]){const t={};l&527&&(t.$$scope={dirty:l,ctx:s}),e.$set(t)},i(s){o||(H(e.$$.fragment,s),o=!0)},o(s){N(e.$$.fragment,s),o=!1},d(s){T(e,s)}}}function le(f,e,o){let s,{params:l}=e,t="",r="",p=!1;async function d(){if(!p){o(2,p=!0);try{await W.Admins.confirmPasswordReset(l==null?void 0:l.token,t,r),Y("Successfully set a new admin password."),Z("/")}catch(g){W.errorResponseHandler(g)}o(2,p=!1)}}function n(){t=this.value,o(0,t)}function i(){r=this.value,o(1,r)}return f.$$set=g=>{"params"in g&&o(5,l=g.params)},f.$$.update=()=>{f.$$.dirty&32&&o(3,s=M.getJWTPayload(l==null?void 0:l.token).email||"")},[t,r,p,s,d,l,n,i]}class ae extends E{constructor(e){super(),G(this,e,le,se,I,{params:5})}}export{ae as default};
 | 
			
		||||
import{S as E,i as G,s as I,F as K,c as F,m as B,t as H,a as N,d as T,C as M,q as J,e as c,w as q,b as k,f as u,r as L,g as b,h as _,u as h,v as O,j as Q,l as U,o as w,A as V,p as W,B as X,D as Y,x as Z,z as S}from"./index.37ad3629.js";function y(f){let e,o,s;return{c(){e=q("for "),o=c("strong"),s=q(f[3]),u(o,"class","txt-nowrap")},m(l,t){b(l,e,t),b(l,o,t),_(o,s)},p(l,t){t&8&&Z(s,l[3])},d(l){l&&w(e),l&&w(o)}}}function x(f){let e,o,s,l,t,r,p,d;return{c(){e=c("label"),o=q("New password"),l=k(),t=c("input"),u(e,"for",s=f[8]),u(t,"type","password"),u(t,"id",r=f[8]),t.required=!0,t.autofocus=!0},m(n,i){b(n,e,i),_(e,o),b(n,l,i),b(n,t,i),S(t,f[0]),t.focus(),p||(d=h(t,"input",f[6]),p=!0)},p(n,i){i&256&&s!==(s=n[8])&&u(e,"for",s),i&256&&r!==(r=n[8])&&u(t,"id",r),i&1&&t.value!==n[0]&&S(t,n[0])},d(n){n&&w(e),n&&w(l),n&&w(t),p=!1,d()}}}function ee(f){let e,o,s,l,t,r,p,d;return{c(){e=c("label"),o=q("New password confirm"),l=k(),t=c("input"),u(e,"for",s=f[8]),u(t,"type","password"),u(t,"id",r=f[8]),t.required=!0},m(n,i){b(n,e,i),_(e,o),b(n,l,i),b(n,t,i),S(t,f[1]),p||(d=h(t,"input",f[7]),p=!0)},p(n,i){i&256&&s!==(s=n[8])&&u(e,"for",s),i&256&&r!==(r=n[8])&&u(t,"id",r),i&2&&t.value!==n[1]&&S(t,n[1])},d(n){n&&w(e),n&&w(l),n&&w(t),p=!1,d()}}}function te(f){let e,o,s,l,t,r,p,d,n,i,g,R,C,v,P,A,j,m=f[3]&&y(f);return r=new J({props:{class:"form-field required",name:"password",$$slots:{default:[x,({uniqueId:a})=>({8:a}),({uniqueId:a})=>a?256:0]},$$scope:{ctx:f}}}),d=new J({props:{class:"form-field required",name:"passwordConfirm",$$slots:{default:[ee,({uniqueId:a})=>({8:a}),({uniqueId:a})=>a?256:0]},$$scope:{ctx:f}}}),{c(){e=c("form"),o=c("div"),s=c("h4"),l=q(`Reset your admin password
 | 
			
		||||
                `),m&&m.c(),t=k(),F(r.$$.fragment),p=k(),F(d.$$.fragment),n=k(),i=c("button"),g=c("span"),g.textContent="Set new password",R=k(),C=c("div"),v=c("a"),v.textContent="Back to login",u(s,"class","m-b-xs"),u(o,"class","content txt-center m-b-sm"),u(g,"class","txt"),u(i,"type","submit"),u(i,"class","btn btn-lg btn-block"),i.disabled=f[2],L(i,"btn-loading",f[2]),u(e,"class","m-b-base"),u(v,"href","/login"),u(v,"class","link-hint"),u(C,"class","content txt-center")},m(a,$){b(a,e,$),_(e,o),_(o,s),_(s,l),m&&m.m(s,null),_(e,t),B(r,e,null),_(e,p),B(d,e,null),_(e,n),_(e,i),_(i,g),b(a,R,$),b(a,C,$),_(C,v),P=!0,A||(j=[h(e,"submit",O(f[4])),Q(U.call(null,v))],A=!0)},p(a,$){a[3]?m?m.p(a,$):(m=y(a),m.c(),m.m(s,null)):m&&(m.d(1),m=null);const z={};$&769&&(z.$$scope={dirty:$,ctx:a}),r.$set(z);const D={};$&770&&(D.$$scope={dirty:$,ctx:a}),d.$set(D),(!P||$&4)&&(i.disabled=a[2]),$&4&&L(i,"btn-loading",a[2])},i(a){P||(H(r.$$.fragment,a),H(d.$$.fragment,a),P=!0)},o(a){N(r.$$.fragment,a),N(d.$$.fragment,a),P=!1},d(a){a&&w(e),m&&m.d(),T(r),T(d),a&&w(R),a&&w(C),A=!1,V(j)}}}function se(f){let e,o;return e=new K({props:{$$slots:{default:[te]},$$scope:{ctx:f}}}),{c(){F(e.$$.fragment)},m(s,l){B(e,s,l),o=!0},p(s,[l]){const t={};l&527&&(t.$$scope={dirty:l,ctx:s}),e.$set(t)},i(s){o||(H(e.$$.fragment,s),o=!0)},o(s){N(e.$$.fragment,s),o=!1},d(s){T(e,s)}}}function le(f,e,o){let s,{params:l}=e,t="",r="",p=!1;async function d(){if(!p){o(2,p=!0);try{await W.Admins.confirmPasswordReset(l==null?void 0:l.token,t,r),X("Successfully set a new admin password."),Y("/")}catch(g){W.errorResponseHandler(g)}o(2,p=!1)}}function n(){t=this.value,o(0,t)}function i(){r=this.value,o(1,r)}return f.$$set=g=>{"params"in g&&o(5,l=g.params)},f.$$.update=()=>{f.$$.dirty&32&&o(3,s=M.getJWTPayload(l==null?void 0:l.token).email||"")},[t,r,p,s,d,l,n,i]}class ae extends E{constructor(e){super(),G(this,e,le,se,I,{params:5})}}export{ae as default};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,2 +1,2 @@
 | 
			
		|||
import{S as E,i as M,s as T,F as j,c as H,m as L,t as w,a as y,d as S,b as g,e as _,f as p,g as k,h as d,j as z,l as B,k as N,n as D,o as v,p as C,q as G,r as F,u as A,v as I,w as h,x as J,y as P,z as R}from"./index.1a8a9cbf.js";function K(c){let e,s,n,l,t,o,f,m,i,a,b,u;return l=new G({props:{class:"form-field required",name:"email",$$slots:{default:[Q,({uniqueId:r})=>({5:r}),({uniqueId:r})=>r?32:0]},$$scope:{ctx:c}}}),{c(){e=_("form"),s=_("div"),s.innerHTML=`<h4 class="m-b-xs">Forgotten admin password</h4> 
 | 
			
		||||
import{S as E,i as M,s as T,F as j,c as H,m as L,t as w,a as y,d as S,b as g,e as _,f as p,g as k,h as d,j as z,l as B,k as N,n as D,o as v,p as C,q as G,r as F,u as A,v as I,w as h,x as J,y as P,z as R}from"./index.37ad3629.js";function K(c){let e,s,n,l,t,o,f,m,i,a,b,u;return l=new G({props:{class:"form-field required",name:"email",$$slots:{default:[Q,({uniqueId:r})=>({5:r}),({uniqueId:r})=>r?32:0]},$$scope:{ctx:c}}}),{c(){e=_("form"),s=_("div"),s.innerHTML=`<h4 class="m-b-xs">Forgotten admin password</h4> 
 | 
			
		||||
                <p>Enter the email associated with your account and we\u2019ll send you a recovery link:</p>`,n=g(),H(l.$$.fragment),t=g(),o=_("button"),f=_("i"),m=g(),i=_("span"),i.textContent="Send recovery link",p(s,"class","content txt-center m-b-sm"),p(f,"class","ri-mail-send-line"),p(i,"class","txt"),p(o,"type","submit"),p(o,"class","btn btn-lg btn-block"),o.disabled=c[1],F(o,"btn-loading",c[1]),p(e,"class","m-b-base")},m(r,$){k(r,e,$),d(e,s),d(e,n),L(l,e,null),d(e,t),d(e,o),d(o,f),d(o,m),d(o,i),a=!0,b||(u=A(e,"submit",I(c[3])),b=!0)},p(r,$){const q={};$&97&&(q.$$scope={dirty:$,ctx:r}),l.$set(q),(!a||$&2)&&(o.disabled=r[1]),$&2&&F(o,"btn-loading",r[1])},i(r){a||(w(l.$$.fragment,r),a=!0)},o(r){y(l.$$.fragment,r),a=!1},d(r){r&&v(e),S(l),b=!1,u()}}}function O(c){let e,s,n,l,t,o,f,m,i;return{c(){e=_("div"),s=_("div"),s.innerHTML='<i class="ri-checkbox-circle-line"></i>',n=g(),l=_("div"),t=_("p"),o=h("Check "),f=_("strong"),m=h(c[0]),i=h(" for the recovery link."),p(s,"class","icon"),p(f,"class","txt-nowrap"),p(l,"class","content"),p(e,"class","alert alert-success")},m(a,b){k(a,e,b),d(e,s),d(e,n),d(e,l),d(l,t),d(t,o),d(t,f),d(f,m),d(t,i)},p(a,b){b&1&&J(m,a[0])},i:P,o:P,d(a){a&&v(e)}}}function Q(c){let e,s,n,l,t,o,f,m;return{c(){e=_("label"),s=h("Email"),l=g(),t=_("input"),p(e,"for",n=c[5]),p(t,"type","email"),p(t,"id",o=c[5]),t.required=!0,t.autofocus=!0},m(i,a){k(i,e,a),d(e,s),k(i,l,a),k(i,t,a),R(t,c[0]),t.focus(),f||(m=A(t,"input",c[4]),f=!0)},p(i,a){a&32&&n!==(n=i[5])&&p(e,"for",n),a&32&&o!==(o=i[5])&&p(t,"id",o),a&1&&t.value!==i[0]&&R(t,i[0])},d(i){i&&v(e),i&&v(l),i&&v(t),f=!1,m()}}}function U(c){let e,s,n,l,t,o,f,m;const i=[O,K],a=[];function b(u,r){return u[2]?0:1}return e=b(c),s=a[e]=i[e](c),{c(){s.c(),n=g(),l=_("div"),t=_("a"),t.textContent="Back to login",p(t,"href","/login"),p(t,"class","link-hint"),p(l,"class","content txt-center")},m(u,r){a[e].m(u,r),k(u,n,r),k(u,l,r),d(l,t),o=!0,f||(m=z(B.call(null,t)),f=!0)},p(u,r){let $=e;e=b(u),e===$?a[e].p(u,r):(N(),y(a[$],1,1,()=>{a[$]=null}),D(),s=a[e],s?s.p(u,r):(s=a[e]=i[e](u),s.c()),w(s,1),s.m(n.parentNode,n))},i(u){o||(w(s),o=!0)},o(u){y(s),o=!1},d(u){a[e].d(u),u&&v(n),u&&v(l),f=!1,m()}}}function V(c){let e,s;return e=new j({props:{$$slots:{default:[U]},$$scope:{ctx:c}}}),{c(){H(e.$$.fragment)},m(n,l){L(e,n,l),s=!0},p(n,[l]){const t={};l&71&&(t.$$scope={dirty:l,ctx:n}),e.$set(t)},i(n){s||(w(e.$$.fragment,n),s=!0)},o(n){y(e.$$.fragment,n),s=!1},d(n){S(e,n)}}}function W(c,e,s){let n="",l=!1,t=!1;async function o(){if(!l){s(1,l=!0);try{await C.Admins.requestPasswordReset(n),s(2,t=!0)}catch(m){C.errorResponseHandler(m)}s(1,l=!1)}}function f(){n=this.value,s(0,n)}return[n,l,t,o,f]}class Y extends E{constructor(e){super(),M(this,e,W,V,T,{})}}export{Y as default};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
import{S as J,i as M,s as N,F as R,c as S,m as U,t as $,a as v,d as z,C as W,E as Y,g as _,k as j,n as A,o as b,p as F,w as y,e as m,f as d,h as k,x as B,q as D,b as C,r as H,u as E,v as G,y as h,z as T}from"./index.1a8a9cbf.js";function I(r){let e,s,t,l,n,o,c,a,i,u,g,q,p=r[3]&&L(r);return o=new D({props:{class:"form-field required",name:"password",$$slots:{default:[O,({uniqueId:f})=>({8:f}),({uniqueId:f})=>f?256:0]},$$scope:{ctx:r}}}),{c(){e=m("form"),s=m("div"),t=m("h4"),l=y(`Type your password to confirm changing your email address
 | 
			
		||||
                    `),p&&p.c(),n=C(),S(o.$$.fragment),c=C(),a=m("button"),i=m("span"),i.textContent="Confirm new email",d(t,"class","m-b-xs"),d(s,"class","content txt-center m-b-sm"),d(i,"class","txt"),d(a,"type","submit"),d(a,"class","btn btn-lg btn-block"),a.disabled=r[1],H(a,"btn-loading",r[1])},m(f,w){_(f,e,w),k(e,s),k(s,t),k(t,l),p&&p.m(t,null),k(e,n),U(o,e,null),k(e,c),k(e,a),k(a,i),u=!0,g||(q=E(e,"submit",G(r[4])),g=!0)},p(f,w){f[3]?p?p.p(f,w):(p=L(f),p.c(),p.m(t,null)):p&&(p.d(1),p=null);const P={};w&769&&(P.$$scope={dirty:w,ctx:f}),o.$set(P),(!u||w&2)&&(a.disabled=f[1]),w&2&&H(a,"btn-loading",f[1])},i(f){u||($(o.$$.fragment,f),u=!0)},o(f){v(o.$$.fragment,f),u=!1},d(f){f&&b(e),p&&p.d(),z(o),g=!1,q()}}}function K(r){let e,s,t,l,n;return{c(){e=m("div"),e.innerHTML=`<div class="icon"><i class="ri-checkbox-circle-line"></i></div> 
 | 
			
		||||
import{S as J,i as M,s as N,F as R,c as S,m as U,t as $,a as v,d as z,C as W,E as Y,g as _,k as j,n as A,o as b,p as F,q as B,e as m,w as y,b as C,f as d,r as H,h as k,u as E,v as D,y as h,x as G,z as T}from"./index.37ad3629.js";function I(r){let e,s,t,l,n,o,c,a,i,u,g,q,p=r[3]&&L(r);return o=new B({props:{class:"form-field required",name:"password",$$slots:{default:[O,({uniqueId:f})=>({8:f}),({uniqueId:f})=>f?256:0]},$$scope:{ctx:r}}}),{c(){e=m("form"),s=m("div"),t=m("h4"),l=y(`Type your password to confirm changing your email address
 | 
			
		||||
                    `),p&&p.c(),n=C(),S(o.$$.fragment),c=C(),a=m("button"),i=m("span"),i.textContent="Confirm new email",d(t,"class","m-b-xs"),d(s,"class","content txt-center m-b-sm"),d(i,"class","txt"),d(a,"type","submit"),d(a,"class","btn btn-lg btn-block"),a.disabled=r[1],H(a,"btn-loading",r[1])},m(f,w){_(f,e,w),k(e,s),k(s,t),k(t,l),p&&p.m(t,null),k(e,n),U(o,e,null),k(e,c),k(e,a),k(a,i),u=!0,g||(q=E(e,"submit",D(r[4])),g=!0)},p(f,w){f[3]?p?p.p(f,w):(p=L(f),p.c(),p.m(t,null)):p&&(p.d(1),p=null);const P={};w&769&&(P.$$scope={dirty:w,ctx:f}),o.$set(P),(!u||w&2)&&(a.disabled=f[1]),w&2&&H(a,"btn-loading",f[1])},i(f){u||($(o.$$.fragment,f),u=!0)},o(f){v(o.$$.fragment,f),u=!1},d(f){f&&b(e),p&&p.d(),z(o),g=!1,q()}}}function K(r){let e,s,t,l,n;return{c(){e=m("div"),e.innerHTML=`<div class="icon"><i class="ri-checkbox-circle-line"></i></div> 
 | 
			
		||||
            <div class="content txt-bold"><p>Email address changed</p> 
 | 
			
		||||
                <p>You can now sign in with your new email address.</p></div>`,s=C(),t=m("button"),t.textContent="Close",d(e,"class","alert alert-success"),d(t,"type","button"),d(t,"class","btn btn-secondary btn-block")},m(o,c){_(o,e,c),_(o,s,c),_(o,t,c),l||(n=E(t,"click",r[6]),l=!0)},p:h,i:h,o:h,d(o){o&&b(e),o&&b(s),o&&b(t),l=!1,n()}}}function L(r){let e,s,t;return{c(){e=y("to "),s=m("strong"),t=y(r[3]),d(s,"class","txt-nowrap")},m(l,n){_(l,e,n),_(l,s,n),k(s,t)},p(l,n){n&8&&B(t,l[3])},d(l){l&&b(e),l&&b(s)}}}function O(r){let e,s,t,l,n,o,c,a;return{c(){e=m("label"),s=y("Password"),l=C(),n=m("input"),d(e,"for",t=r[8]),d(n,"type","password"),d(n,"id",o=r[8]),n.required=!0,n.autofocus=!0},m(i,u){_(i,e,u),k(e,s),_(i,l,u),_(i,n,u),T(n,r[0]),n.focus(),c||(a=E(n,"input",r[7]),c=!0)},p(i,u){u&256&&t!==(t=i[8])&&d(e,"for",t),u&256&&o!==(o=i[8])&&d(n,"id",o),u&1&&n.value!==i[0]&&T(n,i[0])},d(i){i&&b(e),i&&b(l),i&&b(n),c=!1,a()}}}function Q(r){let e,s,t,l;const n=[K,I],o=[];function c(a,i){return a[2]?0:1}return e=c(r),s=o[e]=n[e](r),{c(){s.c(),t=Y()},m(a,i){o[e].m(a,i),_(a,t,i),l=!0},p(a,i){let u=e;e=c(a),e===u?o[e].p(a,i):(j(),v(o[u],1,1,()=>{o[u]=null}),A(),s=o[e],s?s.p(a,i):(s=o[e]=n[e](a),s.c()),$(s,1),s.m(t.parentNode,t))},i(a){l||($(s),l=!0)},o(a){v(s),l=!1},d(a){o[e].d(a),a&&b(t)}}}function V(r){let e,s;return e=new R({props:{nobranding:!0,$$slots:{default:[Q]},$$scope:{ctx:r}}}),{c(){S(e.$$.fragment)},m(t,l){U(e,t,l),s=!0},p(t,[l]){const n={};l&527&&(n.$$scope={dirty:l,ctx:t}),e.$set(n)},i(t){s||($(e.$$.fragment,t),s=!0)},o(t){v(e.$$.fragment,t),s=!1},d(t){z(e,t)}}}function X(r,e,s){let t,{params:l}=e,n="",o=!1,c=!1;async function a(){if(!o){s(1,o=!0);try{await F.Users.confirmEmailChange(l==null?void 0:l.token,n),s(2,c=!0)}catch(g){F.errorResponseHandler(g)}s(1,o=!1)}}const i=()=>window.close();function u(){n=this.value,s(0,n)}return r.$$set=g=>{"params"in g&&s(5,l=g.params)},r.$$.update=()=>{r.$$.dirty&32&&s(3,t=W.getJWTPayload(l==null?void 0:l.token).newEmail||"")},[n,o,c,t,a,l,i,u]}class x extends J{constructor(e){super(),M(this,e,X,V,N,{params:5})}}export{x as default};
 | 
			
		||||
                <p>You can now sign in with your new email address.</p></div>`,s=C(),t=m("button"),t.textContent="Close",d(e,"class","alert alert-success"),d(t,"type","button"),d(t,"class","btn btn-secondary btn-block")},m(o,c){_(o,e,c),_(o,s,c),_(o,t,c),l||(n=E(t,"click",r[6]),l=!0)},p:h,i:h,o:h,d(o){o&&b(e),o&&b(s),o&&b(t),l=!1,n()}}}function L(r){let e,s,t;return{c(){e=y("to "),s=m("strong"),t=y(r[3]),d(s,"class","txt-nowrap")},m(l,n){_(l,e,n),_(l,s,n),k(s,t)},p(l,n){n&8&&G(t,l[3])},d(l){l&&b(e),l&&b(s)}}}function O(r){let e,s,t,l,n,o,c,a;return{c(){e=m("label"),s=y("Password"),l=C(),n=m("input"),d(e,"for",t=r[8]),d(n,"type","password"),d(n,"id",o=r[8]),n.required=!0,n.autofocus=!0},m(i,u){_(i,e,u),k(e,s),_(i,l,u),_(i,n,u),T(n,r[0]),n.focus(),c||(a=E(n,"input",r[7]),c=!0)},p(i,u){u&256&&t!==(t=i[8])&&d(e,"for",t),u&256&&o!==(o=i[8])&&d(n,"id",o),u&1&&n.value!==i[0]&&T(n,i[0])},d(i){i&&b(e),i&&b(l),i&&b(n),c=!1,a()}}}function Q(r){let e,s,t,l;const n=[K,I],o=[];function c(a,i){return a[2]?0:1}return e=c(r),s=o[e]=n[e](r),{c(){s.c(),t=Y()},m(a,i){o[e].m(a,i),_(a,t,i),l=!0},p(a,i){let u=e;e=c(a),e===u?o[e].p(a,i):(j(),v(o[u],1,1,()=>{o[u]=null}),A(),s=o[e],s?s.p(a,i):(s=o[e]=n[e](a),s.c()),$(s,1),s.m(t.parentNode,t))},i(a){l||($(s),l=!0)},o(a){v(s),l=!1},d(a){o[e].d(a),a&&b(t)}}}function V(r){let e,s;return e=new R({props:{nobranding:!0,$$slots:{default:[Q]},$$scope:{ctx:r}}}),{c(){S(e.$$.fragment)},m(t,l){U(e,t,l),s=!0},p(t,[l]){const n={};l&527&&(n.$$scope={dirty:l,ctx:t}),e.$set(n)},i(t){s||($(e.$$.fragment,t),s=!0)},o(t){v(e.$$.fragment,t),s=!1},d(t){z(e,t)}}}function X(r,e,s){let t,{params:l}=e,n="",o=!1,c=!1;async function a(){if(!o){s(1,o=!0);try{await F.Users.confirmEmailChange(l==null?void 0:l.token,n),s(2,c=!0)}catch(g){F.errorResponseHandler(g)}s(1,o=!1)}}const i=()=>window.close();function u(){n=this.value,s(0,n)}return r.$$set=g=>{"params"in g&&s(5,l=g.params)},r.$$.update=()=>{r.$$.dirty&32&&s(3,t=W.getJWTPayload(l==null?void 0:l.token).newEmail||"")},[n,o,c,t,a,l,i,u]}class x extends J{constructor(e){super(),M(this,e,X,V,N,{params:5})}}export{x as default};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
import{S as W,i as Y,s as j,F as A,c as H,m as N,t as P,a as q,d as S,C as B,E as D,g as _,k as G,n as I,o as m,p as z,w as y,e as b,h as w,x as K,q as E,b as C,f as c,r as J,u as h,v as O,y as F,z as R}from"./index.1a8a9cbf.js";function Q(i){let e,l,t,n,s,o,p,a,r,u,v,g,k,L,d=i[4]&&M(i);return o=new E({props:{class:"form-field required",name:"password",$$slots:{default:[X,({uniqueId:f})=>({10:f}),({uniqueId:f})=>f?1024:0]},$$scope:{ctx:i}}}),a=new E({props:{class:"form-field required",name:"passwordConfirm",$$slots:{default:[Z,({uniqueId:f})=>({10:f}),({uniqueId:f})=>f?1024:0]},$$scope:{ctx:i}}}),{c(){e=b("form"),l=b("div"),t=b("h4"),n=y(`Reset your user password
 | 
			
		||||
                    `),d&&d.c(),s=C(),H(o.$$.fragment),p=C(),H(a.$$.fragment),r=C(),u=b("button"),v=b("span"),v.textContent="Set new password",c(t,"class","m-b-xs"),c(l,"class","content txt-center m-b-sm"),c(v,"class","txt"),c(u,"type","submit"),c(u,"class","btn btn-lg btn-block"),u.disabled=i[2],J(u,"btn-loading",i[2])},m(f,$){_(f,e,$),w(e,l),w(l,t),w(t,n),d&&d.m(t,null),w(e,s),N(o,e,null),w(e,p),N(a,e,null),w(e,r),w(e,u),w(u,v),g=!0,k||(L=h(e,"submit",O(i[5])),k=!0)},p(f,$){f[4]?d?d.p(f,$):(d=M(f),d.c(),d.m(t,null)):d&&(d.d(1),d=null);const T={};$&3073&&(T.$$scope={dirty:$,ctx:f}),o.$set(T);const U={};$&3074&&(U.$$scope={dirty:$,ctx:f}),a.$set(U),(!g||$&4)&&(u.disabled=f[2]),$&4&&J(u,"btn-loading",f[2])},i(f){g||(P(o.$$.fragment,f),P(a.$$.fragment,f),g=!0)},o(f){q(o.$$.fragment,f),q(a.$$.fragment,f),g=!1},d(f){f&&m(e),d&&d.d(),S(o),S(a),k=!1,L()}}}function V(i){let e,l,t,n,s;return{c(){e=b("div"),e.innerHTML=`<div class="icon"><i class="ri-checkbox-circle-line"></i></div> 
 | 
			
		||||
import{S as W,i as Y,s as j,F as A,c as H,m as N,t as P,a as q,d as S,C as B,E as D,g as _,k as G,n as I,o as m,p as z,q as E,e as b,w as y,b as C,f as c,r as J,h as w,u as h,v as K,y as F,x as O,z as R}from"./index.37ad3629.js";function Q(i){let e,l,t,n,s,o,p,a,r,u,v,g,k,L,d=i[4]&&M(i);return o=new E({props:{class:"form-field required",name:"password",$$slots:{default:[X,({uniqueId:f})=>({10:f}),({uniqueId:f})=>f?1024:0]},$$scope:{ctx:i}}}),a=new E({props:{class:"form-field required",name:"passwordConfirm",$$slots:{default:[Z,({uniqueId:f})=>({10:f}),({uniqueId:f})=>f?1024:0]},$$scope:{ctx:i}}}),{c(){e=b("form"),l=b("div"),t=b("h4"),n=y(`Reset your user password
 | 
			
		||||
                    `),d&&d.c(),s=C(),H(o.$$.fragment),p=C(),H(a.$$.fragment),r=C(),u=b("button"),v=b("span"),v.textContent="Set new password",c(t,"class","m-b-xs"),c(l,"class","content txt-center m-b-sm"),c(v,"class","txt"),c(u,"type","submit"),c(u,"class","btn btn-lg btn-block"),u.disabled=i[2],J(u,"btn-loading",i[2])},m(f,$){_(f,e,$),w(e,l),w(l,t),w(t,n),d&&d.m(t,null),w(e,s),N(o,e,null),w(e,p),N(a,e,null),w(e,r),w(e,u),w(u,v),g=!0,k||(L=h(e,"submit",K(i[5])),k=!0)},p(f,$){f[4]?d?d.p(f,$):(d=M(f),d.c(),d.m(t,null)):d&&(d.d(1),d=null);const T={};$&3073&&(T.$$scope={dirty:$,ctx:f}),o.$set(T);const U={};$&3074&&(U.$$scope={dirty:$,ctx:f}),a.$set(U),(!g||$&4)&&(u.disabled=f[2]),$&4&&J(u,"btn-loading",f[2])},i(f){g||(P(o.$$.fragment,f),P(a.$$.fragment,f),g=!0)},o(f){q(o.$$.fragment,f),q(a.$$.fragment,f),g=!1},d(f){f&&m(e),d&&d.d(),S(o),S(a),k=!1,L()}}}function V(i){let e,l,t,n,s;return{c(){e=b("div"),e.innerHTML=`<div class="icon"><i class="ri-checkbox-circle-line"></i></div> 
 | 
			
		||||
            <div class="content txt-bold"><p>Password changed</p> 
 | 
			
		||||
                <p>You can now sign in with your new password.</p></div>`,l=C(),t=b("button"),t.textContent="Close",c(e,"class","alert alert-success"),c(t,"type","button"),c(t,"class","btn btn-secondary btn-block")},m(o,p){_(o,e,p),_(o,l,p),_(o,t,p),n||(s=h(t,"click",i[7]),n=!0)},p:F,i:F,o:F,d(o){o&&m(e),o&&m(l),o&&m(t),n=!1,s()}}}function M(i){let e,l,t;return{c(){e=y("for "),l=b("strong"),t=y(i[4])},m(n,s){_(n,e,s),_(n,l,s),w(l,t)},p(n,s){s&16&&K(t,n[4])},d(n){n&&m(e),n&&m(l)}}}function X(i){let e,l,t,n,s,o,p,a;return{c(){e=b("label"),l=y("New password"),n=C(),s=b("input"),c(e,"for",t=i[10]),c(s,"type","password"),c(s,"id",o=i[10]),s.required=!0,s.autofocus=!0},m(r,u){_(r,e,u),w(e,l),_(r,n,u),_(r,s,u),R(s,i[0]),s.focus(),p||(a=h(s,"input",i[8]),p=!0)},p(r,u){u&1024&&t!==(t=r[10])&&c(e,"for",t),u&1024&&o!==(o=r[10])&&c(s,"id",o),u&1&&s.value!==r[0]&&R(s,r[0])},d(r){r&&m(e),r&&m(n),r&&m(s),p=!1,a()}}}function Z(i){let e,l,t,n,s,o,p,a;return{c(){e=b("label"),l=y("New password confirm"),n=C(),s=b("input"),c(e,"for",t=i[10]),c(s,"type","password"),c(s,"id",o=i[10]),s.required=!0},m(r,u){_(r,e,u),w(e,l),_(r,n,u),_(r,s,u),R(s,i[1]),p||(a=h(s,"input",i[9]),p=!0)},p(r,u){u&1024&&t!==(t=r[10])&&c(e,"for",t),u&1024&&o!==(o=r[10])&&c(s,"id",o),u&2&&s.value!==r[1]&&R(s,r[1])},d(r){r&&m(e),r&&m(n),r&&m(s),p=!1,a()}}}function x(i){let e,l,t,n;const s=[V,Q],o=[];function p(a,r){return a[3]?0:1}return e=p(i),l=o[e]=s[e](i),{c(){l.c(),t=D()},m(a,r){o[e].m(a,r),_(a,t,r),n=!0},p(a,r){let u=e;e=p(a),e===u?o[e].p(a,r):(G(),q(o[u],1,1,()=>{o[u]=null}),I(),l=o[e],l?l.p(a,r):(l=o[e]=s[e](a),l.c()),P(l,1),l.m(t.parentNode,t))},i(a){n||(P(l),n=!0)},o(a){q(l),n=!1},d(a){o[e].d(a),a&&m(t)}}}function ee(i){let e,l;return e=new A({props:{nobranding:!0,$$slots:{default:[x]},$$scope:{ctx:i}}}),{c(){H(e.$$.fragment)},m(t,n){N(e,t,n),l=!0},p(t,[n]){const s={};n&2079&&(s.$$scope={dirty:n,ctx:t}),e.$set(s)},i(t){l||(P(e.$$.fragment,t),l=!0)},o(t){q(e.$$.fragment,t),l=!1},d(t){S(e,t)}}}function te(i,e,l){let t,{params:n}=e,s="",o="",p=!1,a=!1;async function r(){if(!p){l(2,p=!0);try{await z.Users.confirmPasswordReset(n==null?void 0:n.token,s,o),l(3,a=!0)}catch(k){z.errorResponseHandler(k)}l(2,p=!1)}}const u=()=>window.close();function v(){s=this.value,l(0,s)}function g(){o=this.value,l(1,o)}return i.$$set=k=>{"params"in k&&l(6,n=k.params)},i.$$.update=()=>{i.$$.dirty&64&&l(4,t=B.getJWTPayload(n==null?void 0:n.token).email||"")},[s,o,p,a,t,r,n,u,v,g]}class le extends W{constructor(e){super(),Y(this,e,te,ee,j,{params:6})}}export{le as default};
 | 
			
		||||
                <p>You can now sign in with your new password.</p></div>`,l=C(),t=b("button"),t.textContent="Close",c(e,"class","alert alert-success"),c(t,"type","button"),c(t,"class","btn btn-secondary btn-block")},m(o,p){_(o,e,p),_(o,l,p),_(o,t,p),n||(s=h(t,"click",i[7]),n=!0)},p:F,i:F,o:F,d(o){o&&m(e),o&&m(l),o&&m(t),n=!1,s()}}}function M(i){let e,l,t;return{c(){e=y("for "),l=b("strong"),t=y(i[4])},m(n,s){_(n,e,s),_(n,l,s),w(l,t)},p(n,s){s&16&&O(t,n[4])},d(n){n&&m(e),n&&m(l)}}}function X(i){let e,l,t,n,s,o,p,a;return{c(){e=b("label"),l=y("New password"),n=C(),s=b("input"),c(e,"for",t=i[10]),c(s,"type","password"),c(s,"id",o=i[10]),s.required=!0,s.autofocus=!0},m(r,u){_(r,e,u),w(e,l),_(r,n,u),_(r,s,u),R(s,i[0]),s.focus(),p||(a=h(s,"input",i[8]),p=!0)},p(r,u){u&1024&&t!==(t=r[10])&&c(e,"for",t),u&1024&&o!==(o=r[10])&&c(s,"id",o),u&1&&s.value!==r[0]&&R(s,r[0])},d(r){r&&m(e),r&&m(n),r&&m(s),p=!1,a()}}}function Z(i){let e,l,t,n,s,o,p,a;return{c(){e=b("label"),l=y("New password confirm"),n=C(),s=b("input"),c(e,"for",t=i[10]),c(s,"type","password"),c(s,"id",o=i[10]),s.required=!0},m(r,u){_(r,e,u),w(e,l),_(r,n,u),_(r,s,u),R(s,i[1]),p||(a=h(s,"input",i[9]),p=!0)},p(r,u){u&1024&&t!==(t=r[10])&&c(e,"for",t),u&1024&&o!==(o=r[10])&&c(s,"id",o),u&2&&s.value!==r[1]&&R(s,r[1])},d(r){r&&m(e),r&&m(n),r&&m(s),p=!1,a()}}}function x(i){let e,l,t,n;const s=[V,Q],o=[];function p(a,r){return a[3]?0:1}return e=p(i),l=o[e]=s[e](i),{c(){l.c(),t=D()},m(a,r){o[e].m(a,r),_(a,t,r),n=!0},p(a,r){let u=e;e=p(a),e===u?o[e].p(a,r):(G(),q(o[u],1,1,()=>{o[u]=null}),I(),l=o[e],l?l.p(a,r):(l=o[e]=s[e](a),l.c()),P(l,1),l.m(t.parentNode,t))},i(a){n||(P(l),n=!0)},o(a){q(l),n=!1},d(a){o[e].d(a),a&&m(t)}}}function ee(i){let e,l;return e=new A({props:{nobranding:!0,$$slots:{default:[x]},$$scope:{ctx:i}}}),{c(){H(e.$$.fragment)},m(t,n){N(e,t,n),l=!0},p(t,[n]){const s={};n&2079&&(s.$$scope={dirty:n,ctx:t}),e.$set(s)},i(t){l||(P(e.$$.fragment,t),l=!0)},o(t){q(e.$$.fragment,t),l=!1},d(t){S(e,t)}}}function te(i,e,l){let t,{params:n}=e,s="",o="",p=!1,a=!1;async function r(){if(!p){l(2,p=!0);try{await z.Users.confirmPasswordReset(n==null?void 0:n.token,s,o),l(3,a=!0)}catch(k){z.errorResponseHandler(k)}l(2,p=!1)}}const u=()=>window.close();function v(){s=this.value,l(0,s)}function g(){o=this.value,l(1,o)}return i.$$set=k=>{"params"in k&&l(6,n=k.params)},i.$$.update=()=>{i.$$.dirty&64&&l(4,t=B.getJWTPayload(n==null?void 0:n.token).email||"")},[s,o,p,a,t,r,n,u,v,g]}class le extends W{constructor(e){super(),Y(this,e,te,ee,j,{params:6})}}export{le as default};
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,3 @@
 | 
			
		|||
import{S as k,i as v,s as y,F as w,c as x,m as C,t as g,a as $,d as L,p as H,E as M,g as r,o as a,e as u,b as m,f,u as _,y as p}from"./index.1a8a9cbf.js";function P(o){let t,s,e,n,i;return{c(){t=u("div"),t.innerHTML=`<div class="icon"><i class="ri-error-warning-line"></i></div> 
 | 
			
		||||
import{S as k,i as v,s as y,F as w,c as x,m as C,t as g,a as $,d as L,p as H,E as M,g as r,o as a,e as u,b as m,f,u as _,y as p}from"./index.37ad3629.js";function P(o){let t,s,e,n,i;return{c(){t=u("div"),t.innerHTML=`<div class="icon"><i class="ri-error-warning-line"></i></div> 
 | 
			
		||||
            <div class="content txt-bold"><p>Invalid or expired verification token.</p></div>`,s=m(),e=u("button"),e.textContent="Close",f(t,"class","alert alert-danger"),f(e,"type","button"),f(e,"class","btn btn-secondary btn-block")},m(l,c){r(l,t,c),r(l,s,c),r(l,e,c),n||(i=_(e,"click",o[4]),n=!0)},p,d(l){l&&a(t),l&&a(s),l&&a(e),n=!1,i()}}}function S(o){let t,s,e,n,i;return{c(){t=u("div"),t.innerHTML=`<div class="icon"><i class="ri-checkbox-circle-line"></i></div> 
 | 
			
		||||
            <div class="content txt-bold"><p>Successfully verified email address.</p></div>`,s=m(),e=u("button"),e.textContent="Close",f(t,"class","alert alert-success"),f(e,"type","button"),f(e,"class","btn btn-secondary btn-block")},m(l,c){r(l,t,c),r(l,s,c),r(l,e,c),n||(i=_(e,"click",o[3]),n=!0)},p,d(l){l&&a(t),l&&a(s),l&&a(e),n=!1,i()}}}function T(o){let t;return{c(){t=u("div"),t.innerHTML='<div class="loader loader-lg"><em>Please wait...</em></div>',f(t,"class","txt-center")},m(s,e){r(s,t,e)},p,d(s){s&&a(t)}}}function F(o){let t;function s(i,l){return i[1]?T:i[0]?S:P}let e=s(o),n=e(o);return{c(){n.c(),t=M()},m(i,l){n.m(i,l),r(i,t,l)},p(i,l){e===(e=s(i))&&n?n.p(i,l):(n.d(1),n=e(i),n&&(n.c(),n.m(t.parentNode,t)))},d(i){n.d(i),i&&a(t)}}}function U(o){let t,s;return t=new w({props:{nobranding:!0,$$slots:{default:[F]},$$scope:{ctx:o}}}),{c(){x(t.$$.fragment)},m(e,n){C(t,e,n),s=!0},p(e,[n]){const i={};n&67&&(i.$$scope={dirty:n,ctx:e}),t.$set(i)},i(e){s||(g(t.$$.fragment,e),s=!0)},o(e){$(t.$$.fragment,e),s=!1},d(e){L(t,e)}}}function V(o,t,s){let{params:e}=t,n=!1,i=!1;l();async function l(){s(1,i=!0);try{await H.Users.confirmVerification(e==null?void 0:e.token),s(0,n=!0)}catch(d){console.warn(d),s(0,n=!1)}s(1,i=!1)}const c=()=>window.close(),b=()=>window.close();return o.$$set=d=>{"params"in d&&s(2,e=d.params)},[n,i,e,c,b]}class E extends k{constructor(t){super(),v(this,t,V,U,y,{params:2})}}export{E as default};
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -20,8 +20,8 @@
 | 
			
		|||
        window.Prism = window.Prism || {};
 | 
			
		||||
        window.Prism.manual = true;
 | 
			
		||||
    </script>
 | 
			
		||||
  <script type="module" crossorigin src="/_/assets/index.1a8a9cbf.js"></script>
 | 
			
		||||
  <link rel="stylesheet" href="/_/assets/index.cbcd76ca.css">
 | 
			
		||||
  <script type="module" crossorigin src="/_/assets/index.37ad3629.js"></script>
 | 
			
		||||
  <link rel="stylesheet" href="/_/assets/index.c21dde00.css">
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
    <div id="app"></div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -922,9 +922,9 @@
 | 
			
		|||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/rollup": {
 | 
			
		||||
      "version": "2.76.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.76.0.tgz",
 | 
			
		||||
      "integrity": "sha512-9jwRIEY1jOzKLj3nsY/yot41r19ITdQrhs+q3ggNWhr9TQgduHqANvPpS32RNpzGklJu3G1AJfvlZLi/6wFgWA==",
 | 
			
		||||
      "version": "2.77.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.0.tgz",
 | 
			
		||||
      "integrity": "sha512-vL8xjY4yOQEw79DvyXLijhnhh+R/O9zpF/LEgkCebZFtb6ELeN9H3/2T0r8+mp+fFTBHZ5qGpOpW2ela2zRt3g==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "bin": {
 | 
			
		||||
        "rollup": "dist/bin/rollup"
 | 
			
		||||
| 
						 | 
				
			
			@ -1662,9 +1662,9 @@
 | 
			
		|||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "rollup": {
 | 
			
		||||
      "version": "2.76.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.76.0.tgz",
 | 
			
		||||
      "integrity": "sha512-9jwRIEY1jOzKLj3nsY/yot41r19ITdQrhs+q3ggNWhr9TQgduHqANvPpS32RNpzGklJu3G1AJfvlZLi/6wFgWA==",
 | 
			
		||||
      "version": "2.77.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.0.tgz",
 | 
			
		||||
      "integrity": "sha512-vL8xjY4yOQEw79DvyXLijhnhh+R/O9zpF/LEgkCebZFtb6ELeN9H3/2T0r8+mp+fFTBHZ5qGpOpW2ela2zRt3g==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "fsevents": "~2.3.2"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -96,6 +96,8 @@
 | 
			
		|||
                readOnlyCompartment.reconfigure(EditorState.readOnly.of(disabled)),
 | 
			
		||||
            ],
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        triggerNativeChange();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $: if (editor && value != editor.state.doc.toString()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -228,7 +230,7 @@
 | 
			
		|||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let options = [{ label: "null" }, { label: "false" }, { label: "true" }];
 | 
			
		||||
        let options = [{ label: "false" }, { label: "true" }];
 | 
			
		||||
 | 
			
		||||
        if (!disableIndirectCollectionsKeys) {
 | 
			
		||||
            options.push({ label: "@collection.*", apply: "@collection." });
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,11 +26,19 @@
 | 
			
		|||
    }
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<OverlayPanel bind:this={panel} class="image-preview" popup on:show on:hide>
 | 
			
		||||
<OverlayPanel bind:this={panel} class="image-preview" btnClose={false} popup on:show on:hide>
 | 
			
		||||
    <svelte:fragment slot="header">
 | 
			
		||||
        <div class="overlay-close" on:click|preventDefault={hide}>
 | 
			
		||||
            <i class="ri-close-line" />
 | 
			
		||||
        </div>
 | 
			
		||||
    </svelte:fragment>
 | 
			
		||||
 | 
			
		||||
    <img src={url} alt="Preview" />
 | 
			
		||||
 | 
			
		||||
    <svelte:fragment slot="footer">
 | 
			
		||||
        <a href={url} class="link-hint txt-ellipsis">/../{url.substring(url.lastIndexOf("/") + 1)}</a>
 | 
			
		||||
        <a href={url} title="Download" class="link-hint txt-ellipsis">
 | 
			
		||||
            /../{url.substring(url.lastIndexOf("/") + 1)}
 | 
			
		||||
        </a>
 | 
			
		||||
        <div class="flex-fill" />
 | 
			
		||||
        <button type="button" class="btn btn-secondary" on:click={hide}>Close</button>
 | 
			
		||||
    </svelte:fragment>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,7 @@
 | 
			
		|||
            transform: rotate(180deg);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    .btn.refreshing i:before {
 | 
			
		||||
        animation: refresh 200ms linear;
 | 
			
		||||
    .btn.refreshing i {
 | 
			
		||||
        animation: refresh 200ms ease-out;
 | 
			
		||||
    }
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -104,7 +104,7 @@
 | 
			
		|||
                    <p>
 | 
			
		||||
                        Example rule:
 | 
			
		||||
                        <br />
 | 
			
		||||
                        <code>@request.user.id!=null && created>"2022-01-01 00:00:00"</code>
 | 
			
		||||
                        <code>@request.user.id!="" && created>"2022-01-01 00:00:00"</code>
 | 
			
		||||
                    </p>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -166,7 +166,7 @@
 | 
			
		|||
 | 
			
		||||
<OverlayPanel
 | 
			
		||||
    bind:this={collectionPanel}
 | 
			
		||||
    class="overlay-panel-lg colored-header collection-panel"
 | 
			
		||||
    class="overlay-panel-lg colored-header compact-header collection-panel"
 | 
			
		||||
    beforeHide={() => {
 | 
			
		||||
        if (hasChanges && confirmClose) {
 | 
			
		||||
            confirm("You have unsaved changes. Do you really want to close the panel?", () => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,6 +67,10 @@
 | 
			
		|||
        field.toDelete = false; // normalize
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $: if (field.required) {
 | 
			
		||||
        field.nullable = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $: interactive = !disabled && !field.system && !field.toDelete && canBeStored;
 | 
			
		||||
 | 
			
		||||
    $: hasErrors = !CommonHelper.isEmpty(CommonHelper.getNestedVal($errors, `schema.${key}`));
 | 
			
		||||
| 
						 | 
				
			
			@ -154,7 +158,7 @@
 | 
			
		|||
        {/if}
 | 
			
		||||
 | 
			
		||||
        {#if expanded && !field.toDelete}
 | 
			
		||||
            <div class="inline-flex flex-gap-sm flex-nowrap" in:fly={{ duration: 200, x: 20, opacity: 0 }}>
 | 
			
		||||
            <div class="inline-flex flex-gap-base flex-nowrap" in:fly={{ duration: 200, x: 20, opacity: 0 }}>
 | 
			
		||||
                <button
 | 
			
		||||
                    type="button"
 | 
			
		||||
                    class="btn btn-sm fade p-l-0 p-r-0"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,7 +44,7 @@
 | 
			
		|||
    {:else if field.type === "file"}
 | 
			
		||||
        <div class="inline-flex">
 | 
			
		||||
            {#each CommonHelper.toArray(record[field.name]) as filename}
 | 
			
		||||
                <figure class="thumb thumb-sm" use:tooltip={filename}>
 | 
			
		||||
                <figure class="thumb thumb-sm">
 | 
			
		||||
                    <RecordFilePreview {record} {filename} />
 | 
			
		||||
                </figure>
 | 
			
		||||
            {/each}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,23 +1,42 @@
 | 
			
		|||
<script>
 | 
			
		||||
    import ApiClient from "@/utils/ApiClient";
 | 
			
		||||
    import CommonHelper from "@/utils/CommonHelper";
 | 
			
		||||
    import PreviewPopup from "@/components/base/PreviewPopup.svelte";
 | 
			
		||||
 | 
			
		||||
    export let record;
 | 
			
		||||
    export let filename;
 | 
			
		||||
 | 
			
		||||
    let previewUrl = "";
 | 
			
		||||
    let previewPopup;
 | 
			
		||||
    let thumbUrl = "";
 | 
			
		||||
    let originalUrl = "";
 | 
			
		||||
 | 
			
		||||
    $: if (CommonHelper.hasImageExtension(filename)) {
 | 
			
		||||
        previewUrl = ApiClient.Records.getFileUrl(record, `${filename}?thumb=100x100`);
 | 
			
		||||
    $: hasPreview = CommonHelper.hasImageExtension(filename);
 | 
			
		||||
 | 
			
		||||
    $: if (hasPreview) {
 | 
			
		||||
        originalUrl = ApiClient.Records.getFileUrl(record, `${filename}`);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $: thumbUrl = originalUrl ? originalUrl + "?thumb=100x100" : "";
 | 
			
		||||
 | 
			
		||||
    function onError() {
 | 
			
		||||
        previewUrl = "";
 | 
			
		||||
        thumbUrl = "";
 | 
			
		||||
    }
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
{#if previewUrl}
 | 
			
		||||
    <img src={previewUrl} alt={filename} on:error={onError} />
 | 
			
		||||
{#if hasPreview}
 | 
			
		||||
    <img
 | 
			
		||||
        src={thumbUrl}
 | 
			
		||||
        alt={filename}
 | 
			
		||||
        title="Preview {filename}"
 | 
			
		||||
        class:link-fade={hasPreview}
 | 
			
		||||
        on:click={(e) => {
 | 
			
		||||
            e.stopPropagation();
 | 
			
		||||
            previewPopup?.show(originalUrl);
 | 
			
		||||
        }}
 | 
			
		||||
        on:error={onError}
 | 
			
		||||
    />
 | 
			
		||||
{:else}
 | 
			
		||||
    <i class="ri-file-line" />
 | 
			
		||||
{/if}
 | 
			
		||||
 | 
			
		||||
<PreviewPopup bind:this={previewPopup} />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
<script>
 | 
			
		||||
    import { createEventDispatcher } from "svelte";
 | 
			
		||||
    import { createEventDispatcher, tick } from "svelte";
 | 
			
		||||
    import { Record } from "pocketbase";
 | 
			
		||||
    import CommonHelper from "@/utils/CommonHelper";
 | 
			
		||||
    import ApiClient from "@/utils/ApiClient";
 | 
			
		||||
| 
						 | 
				
			
			@ -57,12 +57,13 @@
 | 
			
		|||
        return recordPanel?.hide();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function load(model) {
 | 
			
		||||
    async function load(model) {
 | 
			
		||||
        setErrors({}); // reset errors
 | 
			
		||||
        original = model || {};
 | 
			
		||||
        record = model?.clone ? model.clone() : new Record();
 | 
			
		||||
        uploadedFilesMap = {};
 | 
			
		||||
        deletedFileIndexesMap = {};
 | 
			
		||||
        await tick(); // wait to populate the fields to get the normalized values
 | 
			
		||||
        initialFormHash = calculateFormHash(record);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +72,7 @@
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    function save() {
 | 
			
		||||
        if (isSaving || !hasChanges) {
 | 
			
		||||
        if (isSaving || !canSave) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,17 +5,15 @@
 | 
			
		|||
    import tooltip from "@/actions/tooltip";
 | 
			
		||||
    import Field from "@/components/base/Field.svelte";
 | 
			
		||||
    import UploadedFilePreview from "@/components/base/UploadedFilePreview.svelte";
 | 
			
		||||
    import PreviewPopup from "@/components/base/PreviewPopup.svelte";
 | 
			
		||||
    import RecordFilePreview from "@/components/records/RecordFilePreview.svelte";
 | 
			
		||||
 | 
			
		||||
    export let record;
 | 
			
		||||
    export let value = null;
 | 
			
		||||
    export let value = "";
 | 
			
		||||
    export let uploadedFiles = []; // Array<File> array
 | 
			
		||||
    export let deletedFileIndexes = []; // Array<int> array
 | 
			
		||||
    export let field = new SchemaField();
 | 
			
		||||
 | 
			
		||||
    let fileInput;
 | 
			
		||||
    let previewPopup;
 | 
			
		||||
    let filesListElem;
 | 
			
		||||
 | 
			
		||||
    // normalize uploadedFiles type
 | 
			
		||||
| 
						 | 
				
			
			@ -30,8 +28,8 @@
 | 
			
		|||
 | 
			
		||||
    $: isMultiple = field.options?.maxSelect > 1;
 | 
			
		||||
 | 
			
		||||
    $: if (typeof value === "undefined" || value === null) {
 | 
			
		||||
        value = isMultiple ? [] : null;
 | 
			
		||||
    $: if (CommonHelper.isEmpty(value)) {
 | 
			
		||||
        value = isMultiple ? [] : "";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $: valueAsArray = CommonHelper.toArray(value);
 | 
			
		||||
| 
						 | 
				
			
			@ -81,16 +79,7 @@
 | 
			
		|||
    <div bind:this={filesListElem} class="files-list">
 | 
			
		||||
        {#each valueAsArray as filename, i (filename)}
 | 
			
		||||
            <div class="list-item">
 | 
			
		||||
                <figure
 | 
			
		||||
                    class="thumb"
 | 
			
		||||
                    class:fade={deletedFileIndexes.includes(i)}
 | 
			
		||||
                    class:link-fade={CommonHelper.hasImageExtension(filename)}
 | 
			
		||||
                    title={CommonHelper.hasImageExtension(filename) ? "Preview" : ""}
 | 
			
		||||
                    on:click={() =>
 | 
			
		||||
                        CommonHelper.hasImageExtension(filename)
 | 
			
		||||
                            ? previewPopup?.show(ApiClient.Records.getFileUrl(record, filename))
 | 
			
		||||
                            : false}
 | 
			
		||||
                >
 | 
			
		||||
                <figure class="thumb" class:fade={deletedFileIndexes.includes(i)}>
 | 
			
		||||
                    <RecordFilePreview {record} {filename} />
 | 
			
		||||
                </figure>
 | 
			
		||||
                <a
 | 
			
		||||
| 
						 | 
				
			
			@ -173,5 +162,3 @@
 | 
			
		|||
        {/if}
 | 
			
		||||
    </div>
 | 
			
		||||
</Field>
 | 
			
		||||
 | 
			
		||||
<PreviewPopup bind:this={previewPopup} />
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,5 +18,5 @@
 | 
			
		|||
        <i class={CommonHelper.getFieldTypeIcon(field.type)} />
 | 
			
		||||
        <span class="txt">{field.name}</span>
 | 
			
		||||
    </label>
 | 
			
		||||
    <textarea id={uniqueId} required={field.required} class="txt-mono txt-sm" bind:value />
 | 
			
		||||
    <textarea id={uniqueId} required={field.required} class="txt-mono" bind:value />
 | 
			
		||||
</Field>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,7 @@
 | 
			
		|||
    $: isMultiple = field.options?.maxSelect > 1;
 | 
			
		||||
 | 
			
		||||
    $: if (typeof value === "undefined") {
 | 
			
		||||
        value = isMultiple ? [] : null;
 | 
			
		||||
        value = isMultiple ? [] : "";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $: if (isMultiple && Array.isArray(value) && value.length > field.options.maxSelect) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -349,7 +349,7 @@ button {
 | 
			
		|||
        border-color: var(--baseAlt2Color);
 | 
			
		||||
    }
 | 
			
		||||
    &.txt-mono {
 | 
			
		||||
        font-size: var(--smFontSize);
 | 
			
		||||
        line-height: var(--smLineHeight);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -436,9 +436,6 @@ select {
 | 
			
		|||
            line-height: 1;
 | 
			
		||||
            margin-top: -2px;
 | 
			
		||||
            margin-bottom: -2px;
 | 
			
		||||
            + .txt {
 | 
			
		||||
                margin-left: -5px;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    %input, label {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -79,8 +79,8 @@
 | 
			
		|||
            text-align: center;
 | 
			
		||||
            font-size: 1.6rem;
 | 
			
		||||
            line-height: 1;
 | 
			
		||||
            border-top-left-radius: $size;
 | 
			
		||||
            border-bottom-left-radius: $size;
 | 
			
		||||
            border-top-left-radius: 50%;
 | 
			
		||||
            border-bottom-left-radius: 50%;
 | 
			
		||||
            border-top-right-radius: 0;
 | 
			
		||||
            border-bottom-right-radius: 0;
 | 
			
		||||
            color: #fff;
 | 
			
		||||
| 
						 | 
				
			
			@ -154,7 +154,7 @@
 | 
			
		|||
        width: 850px;
 | 
			
		||||
    }
 | 
			
		||||
    &.overlay-panel-lg {
 | 
			
		||||
        width: 650px;
 | 
			
		||||
        width: 700px;
 | 
			
		||||
    }
 | 
			
		||||
    &.overlay-panel-sm {
 | 
			
		||||
        width: 460px;
 | 
			
		||||
| 
						 | 
				
			
			@ -188,13 +188,30 @@
 | 
			
		|||
            padding-top: calc(var(--baseSpacing) - 5px);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    &.compact-header {
 | 
			
		||||
        .panel-header {
 | 
			
		||||
            row-gap: var(--smSpacing);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    &.image-preview {
 | 
			
		||||
        width: auto;
 | 
			
		||||
        min-width: 300px;
 | 
			
		||||
        max-width: 70%;
 | 
			
		||||
        max-height: 90%;
 | 
			
		||||
        .panel-header {
 | 
			
		||||
            position: absolute;
 | 
			
		||||
            z-index: 99;
 | 
			
		||||
            .overlay-close {
 | 
			
		||||
                left: 100%;
 | 
			
		||||
                right: auto;
 | 
			
		||||
                border-top-left-radius: 0;
 | 
			
		||||
                border-bottom-left-radius: 0;
 | 
			
		||||
                border-top-right-radius: 50%;
 | 
			
		||||
                border-bottom-right-radius: 50%;
 | 
			
		||||
                i {
 | 
			
		||||
                    margin-right: 5px;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        .panel-header,
 | 
			
		||||
        .panel-footer {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,7 @@
 | 
			
		|||
    --infoColor:       #3da9fc;
 | 
			
		||||
    --infoAltColor:    #d8eefe;
 | 
			
		||||
    --successColor:    #2cb67d;
 | 
			
		||||
    --successAltColor: #daf6ea;
 | 
			
		||||
    --successAltColor: #d6f5e8;
 | 
			
		||||
    --dangerColor:     #ef4565;
 | 
			
		||||
    --dangerAltColor:  #fcdee4;
 | 
			
		||||
    --warningColor:    #ff8e3c;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -118,15 +118,15 @@ export default class CommonHelper {
 | 
			
		|||
     * Normalizes and returns arr as a valid array instance (if not already).
 | 
			
		||||
     *
 | 
			
		||||
     * @param  {Array}   arr
 | 
			
		||||
     * @param  {Boolean} [allowNull]
 | 
			
		||||
     * @param  {Boolean} [allowEmpty]
 | 
			
		||||
     * @return {Array}
 | 
			
		||||
     */
 | 
			
		||||
    static toArray(arr, allowNull = false) {
 | 
			
		||||
    static toArray(arr, allowEmpty = false) {
 | 
			
		||||
        if (Array.isArray(arr)) {
 | 
			
		||||
            return arr;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return (allowNull || arr !== null) && typeof arr !== "undefined" ? [arr] : [];
 | 
			
		||||
        return (allowEmpty || !CommonHelper.isEmpty(arr)) && typeof arr !== "undefined" ? [arr] : [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue