@@ -45,6 +45,7 @@ type Store struct { | |||
DisplayName string `xorm:"varchar(100)" json:"displayName"` | |||
StorageProvider string `xorm:"varchar(100)" json:"storageProvider"` | |||
ModelProvider string `xorm:"varchar(100)" json:"modelProvider"` | |||
FileTree *File `xorm:"mediumtext" json:"fileTree"` | |||
PropertiesMap map[string]*Properties `xorm:"mediumtext" json:"propertiesMap"` | |||
@@ -304,33 +304,24 @@ class App extends Component { | |||
"/messages")); | |||
if (Setting.isLocalAdminUser(this.state.account)) { | |||
const renderExternalLink = () => { | |||
return ( | |||
<svg style={{marginLeft: "5px"}} width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" className="iconExternalLink_nPIU"> | |||
<path fill="currentColor" | |||
d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path> | |||
</svg> | |||
); | |||
}; | |||
res.push(Setting.getItem( | |||
<a target="_blank" rel="noreferrer" href={Setting.getMyProfileUrl(this.state.account).replace("/account", "/resources")}> | |||
{i18next.t("general:Resources")} | |||
{renderExternalLink()} | |||
{Setting.renderExternalLink()} | |||
</a>, | |||
"#")); | |||
res.push(Setting.getItem( | |||
<a target="_blank" rel="noreferrer" href={Setting.getMyProfileUrl(this.state.account).replace("/account", "/permissions")}> | |||
{i18next.t("general:Permissions")} | |||
{renderExternalLink()} | |||
{Setting.renderExternalLink()} | |||
</a>, | |||
"##")); | |||
res.push(Setting.getItem( | |||
<a target="_blank" rel="noreferrer" href={Setting.getMyProfileUrl(this.state.account).replace("/account", "/records")}> | |||
{i18next.t("general:Logs")} | |||
{renderExternalLink()} | |||
{Setting.renderExternalLink()} | |||
</a>, | |||
"###")); | |||
} | |||
@@ -639,3 +639,12 @@ export function scrollToDiv(divId) { | |||
} | |||
} | |||
} | |||
export function renderExternalLink() { | |||
return ( | |||
<svg style={{marginLeft: "5px"}} width="13.5" height="13.5" aria-hidden="true" viewBox="0 0 24 24" className="iconExternalLink_nPIU"> | |||
<path fill="currentColor" | |||
d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path> | |||
</svg> | |||
); | |||
} |
@@ -16,6 +16,7 @@ import React from "react"; | |||
import {Button, Card, Col, Input, Row, Select} from "antd"; | |||
import * as StoreBackend from "./backend/StoreBackend"; | |||
import * as StorageProviderBackend from "./backend/StorageProviderBackend"; | |||
import * as ProviderBackend from "./backend/ProviderBackend"; | |||
import * as Setting from "./Setting"; | |||
import i18next from "i18next"; | |||
import FileTree from "./FileTree"; | |||
@@ -28,6 +29,7 @@ class StoreEditPage extends React.Component { | |||
owner: props.match.params.owner, | |||
storeName: props.match.params.storeName, | |||
storageProviders: [], | |||
modelProviders: [], | |||
store: null, | |||
}; | |||
} | |||
@@ -35,6 +37,7 @@ class StoreEditPage extends React.Component { | |||
UNSAFE_componentWillMount() { | |||
this.getStore(); | |||
this.getStorageProviders(); | |||
this.getModelProviders(); | |||
} | |||
getStore() { | |||
@@ -67,6 +70,19 @@ class StoreEditPage extends React.Component { | |||
}); | |||
} | |||
getModelProviders() { | |||
ProviderBackend.getProviders(this.props.account.name) | |||
.then((res) => { | |||
if (res.status === "ok") { | |||
this.setState({ | |||
modelProviders: res.data.filter(provider => provider.category === "Model"), | |||
}); | |||
} else { | |||
Setting.showMessage("error", `Failed to get providers: ${res.msg}`); | |||
} | |||
}); | |||
} | |||
parseStoreField(key, value) { | |||
if (["score"].includes(key)) { | |||
value = Setting.myParseInt(value); | |||
@@ -122,6 +138,16 @@ class StoreEditPage extends React.Component { | |||
} /> | |||
</Col> | |||
</Row> | |||
<Row style={{marginTop: "20px"}} > | |||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}> | |||
{i18next.t("store:Model provider")}: | |||
</Col> | |||
<Col span={22} > | |||
<Select virtual={false} style={{width: "100%"}} value={this.state.store.modelProvider} onChange={(value => {this.updateStoreField("modelProvider", value);})} | |||
options={this.state.modelProviders.map((provider) => Setting.getOption(`${provider.displayName} (${provider.name})`, `${provider.name}`)) | |||
} /> | |||
</Col> | |||
</Row> | |||
<Row style={{marginTop: "20px"}} > | |||
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}> | |||
{i18next.t("store:File tree")}: | |||
@@ -55,6 +55,7 @@ class StoreListPage extends React.Component { | |||
createdTime: moment().format(), | |||
displayName: `New Store - ${randomName}`, | |||
storageProvider: "", | |||
modelProvider: "", | |||
propertiesMap: {}, | |||
}; | |||
} | |||
@@ -140,6 +141,28 @@ class StoreListPage extends React.Component { | |||
key: "storageProvider", | |||
width: "250px", | |||
sorter: (a, b) => a.storageProvider.localeCompare(b.storageProvider), | |||
render: (text, record, index) => { | |||
return ( | |||
<a target="_blank" rel="noreferrer" href={Setting.getMyProfileUrl(this.state.account).replace("/account", `/providers/admin/${text}`)}> | |||
{text} | |||
{Setting.renderExternalLink()} | |||
</a> | |||
); | |||
}, | |||
}, | |||
{ | |||
title: i18next.t("store:Model provider"), | |||
dataIndex: "modelProvider", | |||
key: "modelProvider", | |||
width: "250px", | |||
sorter: (a, b) => a.modelProvider.localeCompare(b.modelProvider), | |||
render: (text, record, index) => { | |||
return ( | |||
<Link to={`/providers/${text}`}> | |||
{text} | |||
</Link> | |||
); | |||
}, | |||
}, | |||
{ | |||
title: i18next.t("general:Action"), | |||