|
1 | | -## QOR Admin |
| 1 | +# QOR Admin |
2 | 2 |
|
3 | 3 | Instantly create a beautiful, cross platform, configurable Admin Interface and API for managing your data in minutes. |
4 | 4 |
|
@@ -67,6 +67,159 @@ func main() { |
67 | 67 |
|
68 | 68 | `go run main.go` and visit `localhost:9000/admin` to see the result! |
69 | 69 |
|
| 70 | +## How to use remoteSelector with publish2.version integrated record |
| 71 | + |
| 72 | +### **For has many relationship** |
| 73 | +Suppose we have 2 models Factory and Item. Factory **has many** Items. |
| 74 | + |
| 75 | +In the struct, you need add a field `resource.CompositePrimaryKeyField` to the "many" side, which is `Item` here. |
| 76 | +```go |
| 77 | +type Factory struct { |
| 78 | + gorm.Model |
| 79 | + Name string |
| 80 | + |
| 81 | + publish2.Version |
| 82 | + Items []Item `gorm:"many2many:factory_items;association_autoupdate:false"` |
| 83 | + ItemsSorter sorting.SortableCollection |
| 84 | +} |
| 85 | + |
| 86 | +type Item struct { |
| 87 | + gorm.Model |
| 88 | + Name string |
| 89 | + publish2.Version |
| 90 | + |
| 91 | + // github.com/qor/qor/resource |
| 92 | + resource.CompositePrimaryKeyField // Required |
| 93 | +} |
| 94 | +``` |
| 95 | + |
| 96 | +Then define a remote resource selector. You need configure the `ID` meta like below to make it support composite primary key, this is mandatory. |
| 97 | +```go |
| 98 | +func generateRemoteItemSelector(adm *admin.Admin) (res *admin.Resource) { |
| 99 | + res = adm.AddResource(&Item{}, &admin.Config{Name: "ItemSelector"}) |
| 100 | + res.IndexAttrs("ID", "Name") |
| 101 | + |
| 102 | + // Required. Convert single ID into composite primary key |
| 103 | + res.Meta(&admin.Meta{ |
| 104 | + Name: "ID", |
| 105 | + Valuer: func(value interface{}, ctx *qor.Context) interface{} { |
| 106 | + if r, ok := value.(*Item); ok { |
| 107 | + // github.com/qor/qor/resource |
| 108 | + return resource.GenCompositePrimaryKey(r.ID, r.GetVersionName()) |
| 109 | + } |
| 110 | + return "" |
| 111 | + }, |
| 112 | + }) |
| 113 | + |
| 114 | + return res |
| 115 | +} |
| 116 | +``` |
| 117 | + |
| 118 | +Last, use it in the Factory resource. |
| 119 | +```go |
| 120 | +itemSelector := generateRemoteItemSelector(adm) |
| 121 | +factoryRes.Meta(&admin.Meta{ |
| 122 | + Name: "Items", |
| 123 | + Config: &admin.SelectManyConfig{ |
| 124 | + RemoteDataResource: itemSelector, |
| 125 | + }, |
| 126 | +}) |
| 127 | +``` |
| 128 | + |
| 129 | +### **For has one relationship** |
| 130 | +Suppose we have 2 models. Factory and Manager. Factory **has one** Manager. |
| 131 | + |
| 132 | +First, In the struct, you need add a field `resource.CompositePrimaryKeyField` to the "one" side, which is `Manager` here. |
| 133 | +```go |
| 134 | +type Factory struct { |
| 135 | + gorm.Model |
| 136 | + Name string |
| 137 | + publish2.Version |
| 138 | + |
| 139 | + ManagerID uint |
| 140 | + ManagerVersionName string // Required. in "xxxVersionName" format. |
| 141 | + Manager Manager |
| 142 | +} |
| 143 | + |
| 144 | +type Manager struct { |
| 145 | + gorm.Model |
| 146 | + Name string |
| 147 | + publish2.Version |
| 148 | + |
| 149 | + // github.com/qor/qor/resource |
| 150 | + resource.CompositePrimaryKeyField // Required |
| 151 | +} |
| 152 | +``` |
| 153 | + |
| 154 | +Then define a remote resource selector. You need configure the `ID` meta like below to make it support composite primary key, this is mandatory. |
| 155 | +```go |
| 156 | +func generateRemoteManagerSelector(adm *admin.Admin) (res *admin.Resource) { |
| 157 | + res = adm.AddResource(&Manager{}, &admin.Config{Name: "ManagerSelector"}) |
| 158 | + res.IndexAttrs("ID", "Name") |
| 159 | + |
| 160 | + // Required. Convert single ID into composite primary key |
| 161 | + res.Meta(&admin.Meta{ |
| 162 | + Name: "ID", |
| 163 | + Valuer: func(value interface{}, ctx *qor.Context) interface{} { |
| 164 | + if r, ok := value.(*Manager); ok { |
| 165 | + // github.com/qor/qor/resource |
| 166 | + return resource.GenCompositePrimaryKey(r.ID, r.GetVersionName()) |
| 167 | + } |
| 168 | + return "" |
| 169 | + }, |
| 170 | + }) |
| 171 | + |
| 172 | + return res |
| 173 | +} |
| 174 | + |
| 175 | +Last, use it in the Factory resource. |
| 176 | +```go |
| 177 | +managerSelector := generateRemoteManagerSelector(adm) |
| 178 | +factoryRes.Meta(&admin.Meta{ |
| 179 | + Name: "Manager", |
| 180 | + Config: &admin.SelectOneConfig{ |
| 181 | + RemoteDataResource: managerSelector, |
| 182 | + }, |
| 183 | +}) |
| 184 | +``` |
| 185 | + |
| 186 | +If you need to overwrite Collection. you have to pass composite primary key as the first element of the returning array instead of ID. |
| 187 | +```go |
| 188 | +factoryRes.Meta(&admin.Meta{ |
| 189 | + Name: "Items", |
| 190 | + Config: &admin.SelectManyConfig{ |
| 191 | + Collection: func(value interface{}, ctx *qor.Context) (results [][]string) { |
| 192 | + if c, ok := value.(*Factory); ok { |
| 193 | + var items []Item |
| 194 | + ctx.GetDB().Model(c).Related(&items, "Items") |
| 195 | +
|
| 196 | + for _, p := range items { |
| 197 | + // The first element must be the composite primary key instead of ID |
| 198 | + results = append(results, []string{resource.GenCompositePrimaryKey(p.ID, p.GetVersionName()), p.Name}) |
| 199 | + } |
| 200 | + } |
| 201 | + return |
| 202 | + }, |
| 203 | + RemoteDataResource: itemSelector, |
| 204 | + }, |
| 205 | +}) |
| 206 | +``` |
| 207 | + |
| 208 | +## To support assign associations when creating a new version |
| 209 | +If you want to assign associations when creating a new version of object immediately. You need to define a function called `AssignVersionName` to the versioned struct with **pointer** receiver which should contains the generating new version name's logic and assign the new version name to the object. |
| 210 | +e.g. |
| 211 | +```go |
| 212 | +func (fac *Factory) AssignVersionName(db *gorm.DB) { |
| 213 | + var count int |
| 214 | + name := time.Now().Format("2006-01-02") |
| 215 | + if err := db.Model(&CollectionWithVersion{}).Where("id = ? AND version_name like ?", fac.ID, name+"%").Count(&count).Error; err != nil { |
| 216 | + panic(err) |
| 217 | + } |
| 218 | + fac.VersionName = fmt.Sprintf("%s-v%v", name, count+1) |
| 219 | +} |
| 220 | +``` |
| 221 | +
|
| 222 | +
|
70 | 223 | ## Live DEMO |
71 | 224 |
|
72 | 225 | * Live Demo [http://demo.getqor.com/admin](http://demo.getqor.com/admin) |
|
0 commit comments