You've already forked pocketbase
							
							
				mirror of
				https://github.com/pocketbase/pocketbase.git
				synced 2025-10-31 08:37:38 +02:00 
			
		
		
		
	normalized the caster to return always non-null value and fixed minor ui issues
This commit is contained in:
		| @@ -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, | ||||
| @@ -695,11 +698,12 @@ func TestRecordCreate(t *testing.T) { | ||||
| 			Method: http.MethodPost, | ||||
| 			Url:    "/api/collections/demo2/records", | ||||
| 			Body: strings.NewReader(`{ | ||||
| 				"rel_cascade":"577bd676-aacb-4072-b7da-99d00ee210a4", | ||||
| 				"onerel":"577bd676-aacb-4072-b7da-99d00ee210a4", | ||||
| 				"manyrels":["577bd676-aacb-4072-b7da-99d00ee210a4"], | ||||
| 				"text":"test123", | ||||
| 				"bool":false | ||||
| 				"rel_cascade": "577bd676-aacb-4072-b7da-99d00ee210a4", | ||||
| 				"onerel": "577bd676-aacb-4072-b7da-99d00ee210a4", | ||||
| 				"manyrels" :["577bd676-aacb-4072-b7da-99d00ee210a4"], | ||||
| 				"text": "test123", | ||||
| 				"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
											
										
									
								
							
							
								
								
									
										4
									
								
								ui/dist/index.html
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								ui/dist/index.html
									
									
									
									
										vendored
									
									
								
							| @@ -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> | ||||
|   | ||||
							
								
								
									
										12
									
								
								ui/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										12
									
								
								ui/package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -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] : []; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
		Reference in New Issue
	
	Block a user