Compare commits
No commits in common. "48e55550c3d6761eb8a3145bae2522e4e4ab1974" and "a68d12aab5a0a2e1d1322aae7f3e98de8e4cf937" have entirely different histories.
48e55550c3
...
a68d12aab5
|
|
@ -91,34 +91,6 @@ namespace VELConnect
|
|||
}
|
||||
}
|
||||
|
||||
public class PersistObject
|
||||
{
|
||||
public string id;
|
||||
public readonly DateTime created;
|
||||
public readonly DateTime updated;
|
||||
public string app;
|
||||
public string room;
|
||||
public string network_id;
|
||||
public bool spawned;
|
||||
public string name;
|
||||
public string data;
|
||||
}
|
||||
|
||||
public class RecordList<T>
|
||||
{
|
||||
public int page;
|
||||
public int perPage;
|
||||
public int totalPages;
|
||||
public int totalItems;
|
||||
public List<T> items;
|
||||
}
|
||||
|
||||
public class ComponentState
|
||||
{
|
||||
public int componentIdx;
|
||||
public string state;
|
||||
}
|
||||
|
||||
public class UserCount
|
||||
{
|
||||
[CanBeNull] public readonly string id;
|
||||
|
|
@ -912,24 +884,19 @@ namespace VELConnect
|
|||
}
|
||||
}
|
||||
|
||||
public static void PostRequestCallback(
|
||||
string url,
|
||||
string postData,
|
||||
Dictionary<string, string> headers = null,
|
||||
public static void PostRequestCallback(string url, string postData, Dictionary<string, string> headers = null,
|
||||
Action<string> successCallback = null,
|
||||
Action<string> failureCallback = null,
|
||||
string method = "POST"
|
||||
)
|
||||
Action<string> failureCallback = null)
|
||||
{
|
||||
instance.StartCoroutine(PostRequestCallbackCo(url, postData, headers, successCallback, failureCallback, method));
|
||||
instance.StartCoroutine(PostRequestCallbackCo(url, postData, headers, successCallback, failureCallback));
|
||||
}
|
||||
|
||||
|
||||
private static IEnumerator PostRequestCallbackCo(string url, string postData,
|
||||
Dictionary<string, string> headers = null, Action<string> successCallback = null,
|
||||
Action<string> failureCallback = null, string method="POST")
|
||||
Action<string> failureCallback = null)
|
||||
{
|
||||
UnityWebRequest webRequest = new UnityWebRequest(url, method);
|
||||
UnityWebRequest webRequest = new UnityWebRequest(url, "POST");
|
||||
byte[] bodyRaw = Encoding.UTF8.GetBytes(postData);
|
||||
UploadHandlerRaw uploadHandler = new UploadHandlerRaw(bodyRaw);
|
||||
webRequest.uploadHandler = uploadHandler;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
using UnityEngine;
|
||||
using VELConnect;
|
||||
using VelNet;
|
||||
|
||||
namespace VELConnect
|
||||
|
|
@ -10,6 +14,14 @@ namespace VELConnect
|
|||
{
|
||||
public static VelConnectPersistenceManager instance;
|
||||
|
||||
public class SpawnedObjectData
|
||||
{
|
||||
public string prefabName;
|
||||
public string base64ObjectData;
|
||||
public string networkId;
|
||||
public int componentIdx;
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
instance = this;
|
||||
|
|
@ -27,50 +39,70 @@ namespace VELConnect
|
|||
|
||||
private void OnJoinedRoom(string roomName)
|
||||
{
|
||||
// if we're the first to join this room
|
||||
if (VelNetManager.Players.Count == 1)
|
||||
if (VelNetManager.Players.Count == 0)
|
||||
{
|
||||
VELConnectManager.GetRequestCallback(
|
||||
VELConnectManager.VelConnectUrl +
|
||||
$"/api/collections/PersistObject/records?filter=(app='{Application.productName}')",
|
||||
s =>
|
||||
string spawnedObjects = VELConnectManager.GetRoomData("spawned_objects", "[]");
|
||||
List<string> spawnedObjectList = JsonConvert.DeserializeObject<List<string>>(spawnedObjects);
|
||||
List<NetworkObject> spawnedNetworkObjects = new List<NetworkObject>();
|
||||
GetSpawnedObjectData(spawnedObjectList, (list) =>
|
||||
{
|
||||
foreach (SpawnedObjectData obj in list)
|
||||
{
|
||||
VELConnectManager.RecordList<VELConnectManager.PersistObject> obj =
|
||||
JsonConvert.DeserializeObject<VELConnectManager.RecordList<VELConnectManager.PersistObject>>(s);
|
||||
obj.items = obj.items.Where(i => i.spawned && i.room == VelNetManager.Room).ToList();
|
||||
|
||||
foreach (VELConnectManager.PersistObject persistObject in obj.items)
|
||||
NetworkObject spawnedObj = spawnedNetworkObjects.Find(i => i.networkId == obj.networkId);
|
||||
if (spawnedObj == null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(persistObject.data))
|
||||
{
|
||||
Debug.LogError("Persisted object has no data");
|
||||
continue;
|
||||
}
|
||||
|
||||
NetworkObject spawnedObj = VelNetManager.NetworkInstantiate(persistObject.name, Convert.FromBase64String(persistObject.data));
|
||||
VelNetPersist persist = spawnedObj.GetComponent<VelNetPersist>();
|
||||
|
||||
persist.persistId = persistObject.id;
|
||||
persist.LoadData(persistObject);
|
||||
spawnedObj = VelNetManager.NetworkInstantiate(obj.prefabName);
|
||||
spawnedNetworkObjects.Add(spawnedObj);
|
||||
}
|
||||
}, s => { Debug.LogError("Failed to get persisted spawned objects", this); });
|
||||
|
||||
spawnedObj.syncedComponents[obj.componentIdx].ReceiveBytes(Convert.FromBase64String(obj.base64ObjectData));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// We don't need to register objects, because they will do that automatically when they spawn if they have the VelNetPersist component
|
||||
// We need to unregister objects when they are destroyed because destroying could happen because we left the scene
|
||||
public static void UnregisterObject(NetworkObject obj)
|
||||
private class DataBlocksResponse
|
||||
{
|
||||
VelNetPersist[] persistedComponents = obj.GetComponents<VelNetPersist>();
|
||||
if (persistedComponents.Length > 1)
|
||||
{
|
||||
Debug.LogError("NetworkObject has more than one VelNetPersist component");
|
||||
}
|
||||
public List<VELConnectManager.State.DataBlock> items;
|
||||
}
|
||||
|
||||
private static void GetSpawnedObjectData(List<string> spawnedObjectList, Action<List<SpawnedObjectData>> callback)
|
||||
{
|
||||
VELConnectManager.GetRequestCallback($"/api/collections/DataBlock/records?filter=({string.Join(" || ", "id=\"" + spawnedObjectList + "\"")})", (response) =>
|
||||
{
|
||||
DataBlocksResponse parsedResponse = JsonConvert.DeserializeObject<DataBlocksResponse>(response);
|
||||
callback(parsedResponse.items.Select(i => new SpawnedObjectData()
|
||||
{
|
||||
networkId = i.block_id.Split("_")[-1],
|
||||
componentIdx = int.Parse(i.block_id.Split("_").Last()),
|
||||
prefabName = i.TryGetData("name"),
|
||||
base64ObjectData = i.TryGetData("state")
|
||||
}).ToList());
|
||||
});
|
||||
}
|
||||
|
||||
public static void RegisterObject(NetworkObject obj)
|
||||
{
|
||||
instance.StartCoroutine(instance.RegisterObjectCo(obj));
|
||||
}
|
||||
|
||||
private IEnumerator RegisterObjectCo(NetworkObject obj)
|
||||
{
|
||||
// upload all the persisted components, then add those components to the room data
|
||||
VelNetPersist[] persistedComponents = obj.GetComponents<VelNetPersist>();
|
||||
List<VELConnectManager.State.DataBlock> responses = new List<VELConnectManager.State.DataBlock>();
|
||||
double startTime = Time.timeAsDouble;
|
||||
foreach (VelNetPersist velNetPersist in persistedComponents)
|
||||
{
|
||||
velNetPersist.Delete();
|
||||
velNetPersist.Save(s => { responses.Add(s); });
|
||||
}
|
||||
|
||||
while (responses.Count < persistedComponents.Length && Time.timeAsDouble - startTime < 5)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
VELConnectManager.SetRoomData("spawned_objects", JsonConvert.SerializeObject(responses.Select(i => i.block_id).ToList()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using UnityEngine;
|
||||
|
|
@ -8,20 +7,29 @@ using VelNet;
|
|||
|
||||
namespace VELConnect
|
||||
{
|
||||
public class VelNetPersist : NetworkComponent
|
||||
public class VelNetPersist : MonoBehaviour
|
||||
{
|
||||
private class ComponentState
|
||||
{
|
||||
public int componentIdx;
|
||||
public string state;
|
||||
}
|
||||
|
||||
public SyncState[] syncStateComponents;
|
||||
|
||||
private string Id => $"{Application.productName}_{VelNetManager.Room}_{syncStateComponents.FirstOrDefault()?.networkObject.sceneNetworkId}";
|
||||
|
||||
private const float interval = 5f;
|
||||
private double nextUpdate;
|
||||
private bool loading;
|
||||
private const bool debugLogs = false;
|
||||
public string persistId;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Time.timeAsDouble > nextUpdate && VelNetManager.InRoom && !loading)
|
||||
{
|
||||
nextUpdate = Time.timeAsDouble + interval + UnityEngine.Random.Range(0, interval);
|
||||
if (networkObject.IsMine)
|
||||
if (syncStateComponents.FirstOrDefault()?.networkObject.IsMine == true)
|
||||
{
|
||||
Save();
|
||||
}
|
||||
|
|
@ -46,140 +54,78 @@ namespace VELConnect
|
|||
private void Load()
|
||||
{
|
||||
loading = true;
|
||||
if (debugLogs) Debug.Log($"[VelNetPersist] Loading {name}");
|
||||
|
||||
if (networkObject.isSceneObject)
|
||||
if (debugLogs) Debug.Log($"[VelNetPersist] Loading {Id}");
|
||||
VELConnectManager.GetDataBlock(Id, data =>
|
||||
{
|
||||
// It looks like a PocketBase bug is preventing full filtering from happening:
|
||||
// $"/api/collections/PersistObject/records?filter=(app='{Application.productName}' && room='{VelNetManager.Room}' && network_id='{networkObject.sceneNetworkId}')",
|
||||
VELConnectManager.GetRequestCallback(
|
||||
VELConnectManager.VelConnectUrl +
|
||||
$"/api/collections/PersistObject/records?filter=(app='{Application.productName}')",
|
||||
s =>
|
||||
{
|
||||
VELConnectManager.RecordList<VELConnectManager.PersistObject> obj =
|
||||
JsonConvert.DeserializeObject<VELConnectManager.RecordList<VELConnectManager.PersistObject>>(s);
|
||||
obj.items = obj.items.Where(i => i.network_id == networkObject.sceneNetworkId.ToString() && i.room == VelNetManager.Room).ToList();
|
||||
if (obj.items.Count < 1)
|
||||
{
|
||||
Debug.LogError("[VelNetPersist] No data found for " + name);
|
||||
loading = false;
|
||||
return;
|
||||
}
|
||||
else if (obj.items.Count > 1)
|
||||
{
|
||||
Debug.LogError(
|
||||
$"[VelNetPersist] Multiple records found for app='{Application.productName}' && room='{VelNetManager.Room}' && network_id='{networkObject.sceneNetworkId}'. Using the first one.");
|
||||
}
|
||||
|
||||
LoadData(obj.items.FirstOrDefault());
|
||||
}, s => { loading = false; });
|
||||
}
|
||||
else
|
||||
{
|
||||
VELConnectManager.GetRequestCallback(VELConnectManager.VelConnectUrl + "/api/collections/PersistObject/records/" + persistId, s =>
|
||||
{
|
||||
VELConnectManager.PersistObject obj = JsonConvert.DeserializeObject<VELConnectManager.PersistObject>(s);
|
||||
LoadData(obj);
|
||||
},
|
||||
s => { loading = false; });
|
||||
}
|
||||
}
|
||||
|
||||
public void LoadData(VELConnectManager.PersistObject obj)
|
||||
{
|
||||
if (string.IsNullOrEmpty(obj.data))
|
||||
{
|
||||
Debug.LogError($"[VelNetPersist] No data found for {name}");
|
||||
loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
persistId = obj.id;
|
||||
|
||||
using BinaryReader reader = new BinaryReader(new MemoryStream(Convert.FromBase64String(obj.data)));
|
||||
networkObject.UnpackState(reader);
|
||||
|
||||
if (debugLogs) Debug.Log($"[VelNetPersist] Loaded {name}");
|
||||
loading = false;
|
||||
}
|
||||
|
||||
|
||||
public void Save(Action<VELConnectManager.PersistObject> successCallback = null)
|
||||
{
|
||||
if (debugLogs) Debug.Log($"[VelNetPersist] Saving {name}");
|
||||
|
||||
List<SyncState> syncStateComponents = networkObject.syncedComponents.OfType<SyncState>().ToList();
|
||||
|
||||
if (networkObject == null)
|
||||
{
|
||||
Debug.LogError("NetworkObject is null on SyncState", this);
|
||||
return;
|
||||
}
|
||||
|
||||
using BinaryWriter writer = new BinaryWriter(new MemoryStream());
|
||||
networkObject.PackState(writer);
|
||||
string data = Convert.ToBase64String(((MemoryStream)writer.BaseStream).ToArray());
|
||||
|
||||
// if we have a persistId, update the record, otherwise create a new one
|
||||
if (string.IsNullOrEmpty(persistId))
|
||||
{
|
||||
Debug.LogWarning($"We don't have an existing persistId, so we are creating a new record for {networkObject.name}");
|
||||
VELConnectManager.PostRequestCallback(VELConnectManager.VelConnectUrl + "/api/collections/PersistObject/records", JsonConvert.SerializeObject(
|
||||
new VELConnectManager.PersistObject()
|
||||
{
|
||||
app = Application.productName,
|
||||
room = VelNetManager.Room,
|
||||
network_id = networkObject.sceneNetworkId.ToString(),
|
||||
spawned = !networkObject.isSceneObject,
|
||||
name = networkObject.isSceneObject ? networkObject.name : networkObject.prefabName,
|
||||
data = data,
|
||||
}), null, s =>
|
||||
if (!data.data.TryGetValue("components", out string d))
|
||||
{
|
||||
VELConnectManager.PersistObject resp = JsonConvert.DeserializeObject<VELConnectManager.PersistObject>(s);
|
||||
persistId = resp.id;
|
||||
successCallback?.Invoke(resp);
|
||||
Debug.LogError($"[VelNetPersist] Failed to parse {Id}");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
List<ComponentState> componentData = JsonConvert.DeserializeObject<List<ComponentState>>(d);
|
||||
|
||||
if (componentData.Count != syncStateComponents.Length)
|
||||
{
|
||||
Debug.LogError($"[VelNetPersist] Different number of components");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < syncStateComponents.Length; i++)
|
||||
{
|
||||
syncStateComponents[i].UnpackState(Convert.FromBase64String(componentData[i].state));
|
||||
}
|
||||
|
||||
if (debugLogs) Debug.Log($"[VelNetPersist] Loaded {Id}");
|
||||
loading = false;
|
||||
}, s => { loading = false; });
|
||||
}
|
||||
|
||||
|
||||
public void Save(Action<VELConnectManager.State.DataBlock> successCallback = null)
|
||||
{
|
||||
if (debugLogs) Debug.Log($"[VelNetPersist] Saving {Id}");
|
||||
|
||||
if (syncStateComponents.FirstOrDefault()?.networkObject == null)
|
||||
{
|
||||
Debug.LogError("First SyncState doesn't have a NetworkObject", this);
|
||||
return;
|
||||
}
|
||||
|
||||
List<ComponentState> componentData = new List<ComponentState>();
|
||||
foreach (SyncState syncState in syncStateComponents)
|
||||
{
|
||||
if (syncState == null)
|
||||
{
|
||||
Debug.LogError("SyncState is null for Persist", this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (syncState.networkObject == null)
|
||||
{
|
||||
Debug.LogError("Network Object is null for SyncState", syncState);
|
||||
return;
|
||||
}
|
||||
|
||||
componentData.Add(new ComponentState()
|
||||
{
|
||||
componentIdx = syncState.networkObject.syncedComponents.IndexOf(syncState),
|
||||
state = Convert.ToBase64String(syncState.PackState())
|
||||
});
|
||||
}
|
||||
else
|
||||
|
||||
VELConnectManager.SetDataBlock(Id, new VELConnectManager.State.DataBlock()
|
||||
{
|
||||
VELConnectManager.PostRequestCallback(VELConnectManager.VelConnectUrl + "/api/collections/PersistObject/records/" + persistId, JsonConvert.SerializeObject(
|
||||
new VELConnectManager.PersistObject()
|
||||
{
|
||||
app = Application.productName,
|
||||
room = VelNetManager.Room,
|
||||
network_id = networkObject.sceneNetworkId.ToString(),
|
||||
spawned = !networkObject.isSceneObject,
|
||||
name = networkObject.prefabName,
|
||||
data = data,
|
||||
}), null, s =>
|
||||
id = Id,
|
||||
block_id = Id,
|
||||
category = "object_persist",
|
||||
data = new Dictionary<string, string>
|
||||
{
|
||||
VELConnectManager.PersistObject resp = JsonConvert.DeserializeObject<VELConnectManager.PersistObject>(s);
|
||||
successCallback?.Invoke(resp);
|
||||
}, method: "PATCH");
|
||||
}
|
||||
}
|
||||
|
||||
public void Delete(Action<VELConnectManager.PersistObject> successCallback = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(persistId))
|
||||
{
|
||||
Debug.LogError("We can't delete an object that doesn't have a persistId");
|
||||
return;
|
||||
}
|
||||
|
||||
VELConnectManager.PostRequestCallback(VELConnectManager.VelConnectUrl + "/api/collections/PersistObject/records/" + persistId, null, null,
|
||||
s =>
|
||||
{
|
||||
VELConnectManager.PersistObject resp = JsonConvert.DeserializeObject<VELConnectManager.PersistObject>(s);
|
||||
successCallback?.Invoke(resp);
|
||||
}, Debug.LogError,
|
||||
method: "DELETE");
|
||||
}
|
||||
|
||||
public override void ReceiveBytes(byte[] message)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
{ "name", syncStateComponents.FirstOrDefault()?.networkObject.name },
|
||||
{ "components", JsonConvert.SerializeObject(componentData) }
|
||||
}
|
||||
}, s => { successCallback?.Invoke(s); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "edu.uga.engr.vel.vel-connect",
|
||||
"displayName": "VEL-Connect",
|
||||
"version": "4.0.9",
|
||||
"version": "4.0.8",
|
||||
"unity": "2019.1",
|
||||
"description": "Web-based configuration for VR applications",
|
||||
"keywords": [],
|
||||
|
|
|
|||
|
|
@ -1,126 +0,0 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
jsonData := `{
|
||||
"id": "zo5oymw0d6evw80",
|
||||
"created": "2024-03-14 20:19:38.622Z",
|
||||
"updated": "2024-03-14 20:19:38.622Z",
|
||||
"name": "PersistObject",
|
||||
"type": "base",
|
||||
"system": false,
|
||||
"schema": [
|
||||
{
|
||||
"system": false,
|
||||
"id": "tvwuy2xt",
|
||||
"name": "app",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "mj06ihfs",
|
||||
"name": "room",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "mqw640xp",
|
||||
"name": "network_id",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "f0wynbda",
|
||||
"name": "data",
|
||||
"type": "json",
|
||||
"required": true,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"maxSize": 2000000
|
||||
}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "tqei9ccu",
|
||||
"name": "spawned",
|
||||
"type": "bool",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {}
|
||||
},
|
||||
{
|
||||
"system": false,
|
||||
"id": "sgkbflei",
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"indexes": [],
|
||||
"listRule": "",
|
||||
"viewRule": "",
|
||||
"createRule": "",
|
||||
"updateRule": "",
|
||||
"deleteRule": null,
|
||||
"options": {}
|
||||
}`
|
||||
|
||||
collection := &models.Collection{}
|
||||
if err := json.Unmarshal([]byte(jsonData), &collection); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return daos.New(db).SaveCollection(collection)
|
||||
}, func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("zo5oymw0d6evw80")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return dao.DeleteCollection(collection)
|
||||
})
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/daos"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
"github.com/pocketbase/pocketbase/models/schema"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("zo5oymw0d6evw80")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove
|
||||
collection.Schema.RemoveField("f0wynbda")
|
||||
|
||||
// add
|
||||
new_data := &schema.SchemaField{}
|
||||
if err := json.Unmarshal([]byte(`{
|
||||
"system": false,
|
||||
"id": "9bremliu",
|
||||
"name": "data",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
}
|
||||
}`), new_data); err != nil {
|
||||
return err
|
||||
}
|
||||
collection.Schema.AddField(new_data)
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
}, func(db dbx.Builder) error {
|
||||
dao := daos.New(db);
|
||||
|
||||
collection, err := dao.FindCollectionByNameOrId("zo5oymw0d6evw80")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// add
|
||||
del_data := &schema.SchemaField{}
|
||||
if err := json.Unmarshal([]byte(`{
|
||||
"system": false,
|
||||
"id": "f0wynbda",
|
||||
"name": "data",
|
||||
"type": "json",
|
||||
"required": true,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"options": {
|
||||
"maxSize": 2000000
|
||||
}
|
||||
}`), del_data); err != nil {
|
||||
return err
|
||||
}
|
||||
collection.Schema.AddField(del_data)
|
||||
|
||||
// remove
|
||||
collection.Schema.RemoveField("9bremliu")
|
||||
|
||||
return dao.SaveCollection(collection)
|
||||
})
|
||||
}
|
||||
Loading…
Reference in New Issue