Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions redfish-trawler-frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions redfish-trawler-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"@popperjs/core": "^2.11.8",
"bootstrap": "^5.3.1",
"core-js": "^3.8.3",
"lodash.pick": "^4.4.0",
"vue": "^3.3.4"
},
"devDependencies": {
Expand Down
5 changes: 5 additions & 0 deletions redfish-trawler-frontend/src/assets/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ html, body {
justify-content: center;
align-items: center;
}
.modal {
justify-content: left;
align-items: left;
text-align: left;
}
.title {
justify-content: left;
text-align: left;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/R
<!-- Button trigger modal -->
<!-- TODO: replace each button with vue class? Self check information before accepting -->
<!-- Take advantage of Vues reactive forms -->
<button type="button" class="btn btn-danger btn-sm" data-bs-toggle="modal" data-bs-target="#deleteResourceModal">
<button :id="my_id + 'DeleteModalButton'" type="button" href="#" data-bs-toggle="modal" :data-bs-target="'#' + my_id + 'DeleteModal'">
Delete
</button>
<div class="modal fade" id="deleteResourceModal" tabindex="-1" aria-labelledby="deleteResourceLabel" aria-hidden="true">
<div class="modal fade" :id="my_id + 'DeleteModal'" tabindex="-1" :aria-labelledby="my_id + 'DeleteLabel'" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteResourceLabel">Delete Resource</h5>
<h5 class="modal-title" :id="my_id + 'DeleteLabel'">Delete {{ resource_type }}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Are you sure you want to delete this Resource?
Are you sure you want to delete this {{resource_type}}?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" @click="deleteResource" data-bs-dismiss="modal">Yes</button>
Expand All @@ -34,33 +34,38 @@ License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/R

<script>
import { ref } from 'vue';
let all_id = 0
export default {
name: "ActionDeleteResource",
props: ['service', 'target_id'],
data() {
return {}
beforeCreate() {
all_id += 1;
},
watch: {
target_id: function(new_value) {
this.target_value = new_value
}
},
setup(props) {
setup(props, context) {
const my_id = "PatchPost" + all_id.toString()

const action_info = ref({ })

const action_parameters = ref({ })
const resource_type = ref('Resource')

function deleteResource(event) {
console.log('DELETE NOW')
fetch('/redfish/v1/' + props.target_id + '?service_name=' + props.service, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({})
}).then(response => alert([response.status, response.statusText, '\n'].join(' ')));
}).then(endOfDelete);
}

function endOfDelete(response) {
alert([response.status, response.statusText, '\n'].join(' '))
context.emit("refresh")
}

return { action_info, action_parameters, deleteResource}
return {my_id, resource_type, deleteResource}
}
};
</script>
19 changes: 4 additions & 15 deletions redfish-trawler-frontend/src/components/Actions/ActionModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/R
<!-- Button trigger modal -->
<!-- TODO: replace each button with vue class? Self check information before accepting -->
<!-- Take advantage of Vues reactive forms -->
<button type="button" href="#" data-bs-toggle="modal" :data-bs-target="'#' + my_id + 'Modal'">
<button :disabled="!action_object" :id="my_id + 'ModalButton'" type="button" href="#" data-bs-toggle="modal" :data-bs-target="'#' + my_id + 'Modal'">
{{ short }}
</button>
<div class="modal fade" :id="my_id + 'Modal'" tabindex="-1" :aria-labelledby="my_id + 'Label'" aria-hidden="true">
Expand Down Expand Up @@ -52,35 +52,24 @@ import { ref } from 'vue';
let my_id = 0
export default {
name: "ActionGeneric",
props: ['service', 'title', 'short', 'msg', 'action_uri', 'action_info'],
props: ['service', 'title', 'short', 'msg', 'action_object'],
beforeCreate() {
this.my_id = "Action" + my_id.toString();
my_id += 1;
},
data() {
return {}
},
watch: {
action_info: function(new_value) {
console.log(new_value)
}
},
setup(props) {

const action_info = ref({ })

const action_parameters = ref({ })

function runAction(event) {
console.log('RUNNING ACTION NOW')
fetch('' + props.action_uri + '?service_name=' + props.service, {
fetch('' + props.action_object["target"] + '?service_name=' + props.service, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(action_parameters.value)
}).then(response => alert([response.status, response.statusText, '\n'].join(' ')));
}

return { action_parameters, runAction}
return {action_parameters, runAction}
}
};
</script>
69 changes: 48 additions & 21 deletions redfish-trawler-frontend/src/components/Actions/ActionPatchPost.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,32 +10,38 @@ License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/R
<!-- Button trigger modal -->
<!-- TODO: replace each button with vue class? Self check information before accepting -->
<!-- Take advantage of Vues reactive forms -->
<button type="button" href="#" data-bs-toggle="modal" :data-bs-target="'#' + my_id + 'Modal'">
<a v-if="discrete" href="#" data-bs-toggle="modal" :data-bs-target="'#' + my_id + 'Modal'">
{{ short }}
</a>
<button v-else type="button" href="#" data-bs-toggle="modal" :data-bs-target="'#' + my_id + 'Modal'">
{{ short }}
</button>
<div class="modal fade" :id="my_id + 'Modal'" tabindex="-1" :aria-labelledby="my_id + 'Label'" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" :id="my_id + 'Label'">{{ msg }}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<button :id="my_id + 'Close'" type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3" v-for="(item, key) in action_info" :key="item.option">
<label :for="key+'id'" class="form-label">{{ item.option }}</label>
<select v-if="(typeof item.value == 'object')" class="form-select" :id="key+'id'" v-model="action_parameters[key]">
<label :for="key + my_id" class="form-label">{{ item.option }}</label>
<select v-if="(typeof item.value == 'object')" class="form-select" :id="key+my_id" v-model="action_parameters[key]">
<option value="" selected disabled> Select Item </option>
<option v-for="val in item.value" :key="val" :value="val">{{ val }}</option>
</select>
<select v-else-if="(typeof item.value == 'boolean')" class="form-select" :id="key+'id'" v-model="action_parameters[key]">
<select v-else-if="(typeof item.value == 'boolean')" class="form-select" :id="key+my_id" v-model="action_parameters[key]">
<option :value="true">True</option>
<option :value="false">False</option>
</select>
<input v-else :id="key+'id'" type="text" class="form-control" placeholder="" v-model="action_parameters[key]">
<input v-else :id="key + my_id" :type="item.hidden ? 'password' : 'text'" class="form-control" placeholder="" v-model="action_parameters[key]">
<div v-if="item.hidden" class="mb-3"></div>
<label v-if="item.hidden" :for="key+my_id+'Confirm'" class="form-label">Confirm {{ item.option }}</label>
<input v-if="item.hidden" :id="key+my_id+'Confirm'" :type="item.hidden ? 'password' : 'text'" class="form-control" placeholder="" v-model="action_parameters[key + 'Confirm']">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" @click="postWithForm" data-bs-dismiss="modal">OK</button>
<button type="button" class="btn btn-danger" @click="postWithForm">OK</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
</div>
</div>
Expand All @@ -45,35 +51,32 @@ License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/R

<script>
import { ref } from 'vue';
let my_id = 0
let all_id = 0
export default {
name: "ActionPatchPost",
props: ['service', 'title', 'short', 'msg', 'action_uri', 'action_info', 'call_type'],
props: ['service', 'title', 'short', 'msg', 'action_uri', 'action_info', 'call_type', 'my_callback', 'discrete'],
beforeCreate() {
this.my_id = "PatchPost" + my_id.toString();
my_id += 1;
all_id += 1;
for (let item in this.action_info){
let target = this.action_info[item].target
if (target) {
this.action_parameters[target] = {}
}
}
},
data() {
return {}
},
watch: {
action_info: function(new_value) {
}
},
setup(props) {
setup(props, context) {
const my_id = "PatchPost" + all_id.toString()

const action_parameters = ref({ })

function postWithForm(event) {
console.log(props.call_type + 'NOW')

let output_json = {}
for (let item in action_parameters.value){
if (item === 'PasswordConfirm') {
continue
}
let path = item.split('.', 2)
if (path.length > 1){
if (!output_json[path[0]]) {
Expand All @@ -85,14 +88,38 @@ export default {
output_json[path[0]] = action_parameters.value[item]
}
}

if ('Password' in props.action_info){
if (action_parameters.value['Password']){
if (action_parameters.value['Password'] !== action_parameters.value['PasswordConfirm']){
alert('Passwords do not match')
return
}
}
else {
alert('Please enter a password')
return
}
}

fetch('' + props.action_uri + '?service_name=' + props.service, {
method: props.call_type,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(output_json),
}).then(response => alert([response.status, response.statusText, '\n'].join(' ')));
}).then(endOfPostForm);
}

function endOfPostForm(response) {
for (let item in action_parameters.value){
action_parameters.value[item] = ''
}
alert([response.status, response.statusText, '\n'].join(' '))
console.log(my_id)
document.getElementById(my_id + "Close").click()
context.emit("refresh")
}

return { action_parameters, postWithForm}
return {my_id, action_parameters, postWithForm}
}
};
</script>
6 changes: 3 additions & 3 deletions redfish-trawler-frontend/src/components/MainUI/TopBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/R
<template>
<div class="bar d-flex">
<select class="form-select" id="current_service" @change="$emit('changeService', current_service)" v-model="current_service">
<option disabled>Select a Service</option>
<option disabled selected>Select a Service</option>
<option v-for="(host_url, service_name) in services" :key="service_name" :value="service_name">
{{ service_name }} - {{ host_url }}
</option>
Expand All @@ -35,7 +35,7 @@ License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/R
<select v-if="(typeof item.value == 'object')" :key="val" class="form-select" :id="key+'id'" v-model="new_service_info[key]">
<option v-for="val in item.value" :key="val" :value="val">{{ val }}</option>
</select>
<input v-else :id="key+'id'" type="text" class="form-control" v-model="new_service_info[key]" placeholder="">
<input v-else :id="key+'id'" :type="item.hidden ? 'password': 'text'" class="form-control" v-model="new_service_info[key]" placeholder="">
</div>
</form>
</div>
Expand Down Expand Up @@ -64,7 +64,7 @@ export default {
'nickname': {'option': "Nickname (optional)", 'value':''},
'hostname': {'option': "Hostname", 'value':'http://127.0.0.1:8000'},
'username': {'option': "Username", 'value':'-'},
'password': {'option': "Password", 'value':''},
'password': {'option': "Password", 'value':'', 'hidden': true},
'logintype': {'option': "LoginType", 'value':['Basic', 'Session', 'None']}
}
)
Expand Down
32 changes: 20 additions & 12 deletions redfish-trawler-frontend/src/components/Pages/UserManagement.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/R
<!-- Use Vue template for a basic Table, on all collections -->
<div v-if="view==='table'">
<div class="title">Accounts
<ActionPatchPost :service="service" :action_uri="'/redfish/v1/AccountService/Accounts'"
<ActionPatchPost :service="service" :action_uri="'/redfish/v1/AccountService/Accounts'" @refresh="gotoTable"
:action_info="action_params['post_account']" :msg="'Add New Account'" :short="'Add new'" :call_type="'POST'"/>
</div>
<TableAccounts :payload="page_payload['_accounts']" @gotoaccount="elem => gotoResource(elem)"/>
<TableRoles :payload="page_payload['_roles']" @gotorole="elem => gotoResource(elem)"/>
<div class="title" v-if="view==='table'">Properties
<ActionPatchPost :service="service" :action_uri="'/redfish/v1/AccountService'"
:action_info="action_params['patch_service']" :msg="'Modify Properties'" :short="'Modify'" :call_type="'PATCH'"/>
<TableAccounts :payload="page_payload['_accounts']" :service="service" @refresh="gotoTable"/>
<TableRoles :payload="page_payload['_roles']" />
<div class="title" v-if="view==='table'">Account Service Settings
<ActionPatchPost :service="service" :action_uri="'/redfish/v1/AccountService'" @refresh="gotoTable"
:action_info="pick_params(action_params['patch_service'], Object.keys(page_payload['_payload']))" :msg="'Modify Properties'" :short="'Modify'" :call_type="'PATCH'"/>
</div>
<div class="propertyblock">
<div v-for="entry in ['ServiceEnabled', 'AuthFailureLoggingThreshold', 'MinPasswordLength',
'AccountLockoutDuration', 'AccountLockoutThreshold', 'AccountLockoutCounterResetAfter']" :key="entry">
{{ entry }}: {{ page_payload['_payload'][entry] }}
</div>
<template v-for="entry in ['ServiceEnabled', 'AuthFailureLoggingThreshold', 'MinPasswordLength',
'AccountLockoutDuration', 'AccountLockoutThreshold', 'AccountLockoutCounterResetAfter']">
<div v-if="entry in page_payload['_payload']" :key="entry">{{ entry }}: {{ page_payload['_payload'][entry] }}</div>
</template>
</div>
</div>

Expand All @@ -35,6 +35,7 @@ License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/R

<script>
import { ref } from 'vue';
import * as _ from "lodash";
import TableAccounts from '../Tables/Accounts.vue';
import TableRoles from '../Tables/Roles.vue';
import ActionPatchPost from '../Actions/ActionPatchPost.vue';
Expand All @@ -47,8 +48,14 @@ export default {
ActionPatchPost,
ResourceGeneric
},
methods: {
// move this to generic modal for all actions to use/filter keys
pick_params(current, expected) {
return _.pick(current, expected)
},
},
props: ['service'],
watch: { },
watch: {},
setup(props) {
// change value of a const ref with .value
const page_payload = ref({'_payload': {}})
Expand All @@ -59,7 +66,7 @@ export default {
'Locked': {'option': "Locked", 'value':true},
'Description': {'option': 'Description', 'value': 0},
'UserName': {'option': 'UserName', 'value': 0},
'Password': {'option': 'Password', 'value': 0},
'Password': {'option': 'Password', 'value': 0, 'hidden': true},
'RoleId': {'option': 'RoleId', 'value': 0}
},
"patch_service": {
Expand All @@ -73,6 +80,7 @@ export default {
}
)


function gotoTable() {
// TODO: move to its own shared function
fetch('/page-view?service_name=' + props.service + '&page_name=usermanagement', {
Expand Down
Loading