added search bar for client management page

This commit is contained in:
vladimir.kuznetsov 2023-11-23 14:32:16 +07:00
parent e8ceeb6e20
commit 5dc3b64e0b
9 changed files with 82 additions and 36 deletions

View file

@ -0,0 +1,6 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="x, &#195;&#151;, close">
<path id="Vector" d="M18 6L6 18" stroke="#D7D8DB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="Vector_2" d="M6 6L18 18" stroke="#D7D8DB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 374 B

View file

@ -0,0 +1,6 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="search">
<path id="Vector" d="M11 19C15.4183 19 19 15.4183 19 11C19 6.58172 15.4183 3 11 3C6.58172 3 3 6.58172 3 11C3 15.4183 6.58172 19 11 19Z" stroke="#D7D8DB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path id="Vector_2" d="M21.0004 20.9984L16.6504 16.6484" stroke="#D7D8DB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 483 B

View file

@ -223,5 +223,7 @@
<file>server_scripts/awg/run_container.sh</file> <file>server_scripts/awg/run_container.sh</file>
<file>server_scripts/awg/Dockerfile</file> <file>server_scripts/awg/Dockerfile</file>
<file>ui/qml/Pages2/PageShareFullAccess.qml</file> <file>ui/qml/Pages2/PageShareFullAccess.qml</file>
<file>images/controls/close.svg</file>
<file>images/controls/search.svg</file>
</qresource> </qresource>
</RCC> </RCC>

View file

@ -232,6 +232,14 @@ void ExportController::exportConfig(const QString &fileName)
SystemController::saveFile(fileName, m_config); SystemController::saveFile(fileName, m_config);
} }
void ExportController::updateClientManagementModel(const DockerContainer container, ServerCredentials credentials)
{
ErrorCode errorCode = m_clientManagementModel->updateModel(container, credentials);
if (errorCode != ErrorCode::NoError) {
emit exportErrorOccurred(errorString(errorCode));
}
}
void ExportController::revokeConfig(const int row, const DockerContainer container, ServerCredentials credentials) void ExportController::revokeConfig(const int row, const DockerContainer container, ServerCredentials credentials)
{ {
ErrorCode errorCode = m_clientManagementModel->revokeClient(row, container, credentials); ErrorCode errorCode = m_clientManagementModel->revokeClient(row, container, credentials);

View file

@ -39,6 +39,7 @@ public slots:
void exportConfig(const QString &fileName); void exportConfig(const QString &fileName);
void updateClientManagementModel(const DockerContainer container, ServerCredentials credentials);
void revokeConfig(const int row, const DockerContainer container, ServerCredentials credentials); void revokeConfig(const int row, const DockerContainer container, ServerCredentials credentials);
void renameClient(const int row, const QString &clientName, const DockerContainer container, ServerCredentials credentials); void renameClient(const int row, const QString &clientName, const DockerContainer container, ServerCredentials credentials);

View file

@ -40,9 +40,6 @@ QVariant ClientManagementModel::data(const QModelIndex &index, int role) const
switch (role) { switch (role) {
case ClientNameRole: return userData.value(configKey::clientName).toString(); case ClientNameRole: return userData.value(configKey::clientName).toString();
case ContainerNameRole:
return ContainerProps::containerHumanNames().value(
static_cast<DockerContainer>(userData.value(configKey::container).toInt()));
} }
return QVariant(); return QVariant();
@ -50,6 +47,9 @@ QVariant ClientManagementModel::data(const QModelIndex &index, int role) const
ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCredentials credentials) ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCredentials credentials)
{ {
beginResetModel();
m_clientsTable = QJsonArray();
ServerController serverController(m_settings); ServerController serverController(m_settings);
ErrorCode error = ErrorCode::NoError; ErrorCode error = ErrorCode::NoError;
@ -60,10 +60,10 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr
serverController.getTextFileFromContainer(container, credentials, clientsTableFile, &error); serverController.getTextFileFromContainer(container, credentials, clientsTableFile, &error);
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
logger.error() << "Failed to get the clientsTable file from the server"; logger.error() << "Failed to get the clientsTable file from the server";
endResetModel();
return error; return error;
} }
beginResetModel();
m_clientsTable = QJsonDocument::fromJson(clientsTableString).array(); m_clientsTable = QJsonDocument::fromJson(clientsTableString).array();
if (m_clientsTable.isEmpty()) { if (m_clientsTable.isEmpty()) {
@ -76,6 +76,7 @@ ErrorCode ClientManagementModel::updateModel(DockerContainer container, ServerCr
error = getWireGuardClients(serverController, container, credentials, count); error = getWireGuardClients(serverController, container, credentials, count);
} }
if (error != ErrorCode::NoError) { if (error != ErrorCode::NoError) {
endResetModel();
return error; return error;
} }
@ -124,7 +125,6 @@ ErrorCode ClientManagementModel::getOpenVpnClients(ServerController &serverContr
QJsonObject userData; QJsonObject userData;
userData[configKey::clientName] = QString("Client %1").arg(count); userData[configKey::clientName] = QString("Client %1").arg(count);
userData[configKey::container] = container;
client[configKey::userData] = userData; client[configKey::userData] = userData;
m_clientsTable.push_back(client); m_clientsTable.push_back(client);
@ -165,7 +165,6 @@ ErrorCode ClientManagementModel::getWireGuardClients(ServerController &serverCon
QJsonObject userData; QJsonObject userData;
userData[configKey::clientName] = QString("Client %1").arg(count); userData[configKey::clientName] = QString("Client %1").arg(count);
userData[configKey::container] = container;
client[configKey::userData] = userData; client[configKey::userData] = userData;
m_clientsTable.push_back(client); m_clientsTable.push_back(client);
@ -211,7 +210,6 @@ ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QSt
QJsonObject userData; QJsonObject userData;
userData[configKey::clientName] = clientName; userData[configKey::clientName] = clientName;
userData[configKey::container] = container;
client[configKey::userData] = userData; client[configKey::userData] = userData;
m_clientsTable.push_back(client); m_clientsTable.push_back(client);
endResetModel(); endResetModel();
@ -371,6 +369,5 @@ QHash<int, QByteArray> ClientManagementModel::roleNames() const
{ {
QHash<int, QByteArray> roles; QHash<int, QByteArray> roles;
roles[ClientNameRole] = "clientName"; roles[ClientNameRole] = "clientName";
roles[ContainerNameRole] = "containerName";
return roles; return roles;
} }

View file

@ -11,26 +11,9 @@ class ClientManagementModel : public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
struct ClientManagementData
{
QString userId;
QJsonObject userData;
bool operator==(const ClientManagementData &r) const
{
return userId == r.userId;
}
bool operator==(const QString &otherUserId) const
{
return userId == otherUserId;
}
};
public: public:
enum Roles { enum Roles {
ClientNameRole = Qt::UserRole + 1, ClientNameRole = Qt::UserRole + 1,
ContainerNameRole,
}; };
ClientManagementModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr); ClientManagementModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);

View file

@ -87,6 +87,7 @@ Switch {
id: content id: content
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
ListItemTitleType { ListItemTitleType {
Layout.fillWidth: true Layout.fillWidth: true

View file

@ -76,6 +76,7 @@ PageType {
} }
} }
property bool isSearchBarVisible: false
property bool showContent: false property bool showContent: false
property bool shareButtonEnabled: true property bool shareButtonEnabled: true
property list<QtObject> connectionTypesModel: [ property list<QtObject> connectionTypesModel: [
@ -205,8 +206,8 @@ PageType {
onClicked: { onClicked: {
accessTypeSelector.currentIndex = 1 accessTypeSelector.currentIndex = 1
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
ClientManagementModel.updateModel(ContainersModel.getCurrentlyProcessedContainerIndex(), ExportController.updateClientManagementModel(ContainersModel.getCurrentlyProcessedContainerIndex(),
ServersModel.getCurrentlyProcessedServerCredentials()) ServersModel.getCurrentlyProcessedServerCredentials())
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
} }
} }
@ -354,12 +355,12 @@ PageType {
ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(currentIndex)) ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(currentIndex))
if (accessTypeSelector.currentIndex === 0) { fillConnectionTypeModel()
fillConnectionTypeModel()
} else { if (accessTypeSelector.currentIndex === 1) {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
ClientManagementModel.updateModel(ContainersModel.getCurrentlyProcessedContainerIndex(), ExportController.updateClientManagementModel(ContainersModel.getCurrentlyProcessedContainerIndex(),
ServersModel.getCurrentlyProcessedServerCredentials()) ServersModel.getCurrentlyProcessedServerCredentials())
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
} }
} }
@ -444,9 +445,36 @@ PageType {
Layout.topMargin: 24 Layout.topMargin: 24
Layout.bottomMargin: 16 Layout.bottomMargin: 16
visible: accessTypeSelector.currentIndex === 1 visible: accessTypeSelector.currentIndex === 1 && !root.isSearchBarVisible
headerText: qsTr("Users") headerText: qsTr("Users")
actionButtonImage: "qrc:/images/controls/search.svg"
actionButtonFunction: function() {
root.isSearchBarVisible = true
}
}
RowLayout {
Layout.topMargin: 24
Layout.bottomMargin: 16
visible: accessTypeSelector.currentIndex === 1 && root.isSearchBarVisible
TextFieldWithHeaderType {
id: searchTextField
Layout.fillWidth: true
textFieldPlaceholderText: qsTr("Search")
}
ImageButtonType {
image: "qrc:/images/controls/close.svg"
imageColor: "#D7D8DB"
onClicked: function() {
root.isSearchBarVisible = false
searchTextField.textFieldText = ""
}
}
} }
ListView { ListView {
@ -456,7 +484,15 @@ PageType {
visible: accessTypeSelector.currentIndex === 1 visible: accessTypeSelector.currentIndex === 1
model: ClientManagementModel model: SortFilterProxyModel {
id: proxyClientManagementModel
sourceModel: ClientManagementModel
filters: RegExpFilter {
roleName: "clientName"
pattern: ".*" + searchTextField.textFieldText + ".*"
caseSensitivity: Qt.CaseInsensitive
}
}
clip: true clip: true
interactive: false interactive: false
@ -479,7 +515,6 @@ PageType {
Layout.fillWidth: true Layout.fillWidth: true
text: clientName text: clientName
descriptionText: containerName
rightImageSource: "qrc:/images/controls/chevron-right.svg" rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() { clickedFunction: function() {
@ -510,7 +545,7 @@ PageType {
Layout.bottomMargin: 24 Layout.bottomMargin: 24
headerText: clientName headerText: clientName
descriptionText: serverSelector.text + ", " + containerName descriptionText: serverSelector.text
} }
BasicButtonType { BasicButtonType {
@ -620,4 +655,11 @@ PageType {
} }
} }
} }
MouseArea {
anchors.fill: parent
onPressed: function(mouse) {
forceActiveFocus()
mouse.accepted = false
}
}
} }