mirror of
https://github.com/aljazceru/CTFd.git
synced 2025-12-17 05:54:19 +01:00
Add basic interface for interacting with field entries
This commit is contained in:
102
CTFd/themes/admin/assets/js/components/configs/fields/Field.vue
Normal file
102
CTFd/themes/admin/assets/js/components/configs/fields/Field.vue
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
<template>
|
||||||
|
<div class="border-bottom">
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="close float-right"
|
||||||
|
aria-label="Close"
|
||||||
|
@click="deleteField()"
|
||||||
|
>
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Field Type</label>
|
||||||
|
<select class="form-control custom-select">
|
||||||
|
<option>Text Field</option>
|
||||||
|
<option>Checkbox</option>
|
||||||
|
</select>
|
||||||
|
<small class="form-text text-muted">Type of field shown to the user</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Field Name</label>
|
||||||
|
<input type="text" class="form-control" v-model.lazy="field.name">
|
||||||
|
<small class="form-text text-muted">Field name</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Field Description</label>
|
||||||
|
<input type="text" class="form-control" v-model.lazy="field.description">
|
||||||
|
<small id="emailHelp" class="form-text text-muted">Field Description</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="form-check">
|
||||||
|
<label class="form-check-label">
|
||||||
|
<input class="form-check-input" type="checkbox" v-model.lazy="field.editable"> Editable by user in profile
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<label class="form-check-label">
|
||||||
|
<input class="form-check-input" type="checkbox" v-model.lazy="field.required"> Required on registration
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<label class="form-check-label">
|
||||||
|
<input class="form-check-input" type="checkbox" v-model.lazy="field.public"> Shown on public profile
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row pb-3">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<div class="d-block">
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-success btn-outlined float-right"
|
||||||
|
type="button"
|
||||||
|
@click="saveField()"
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
index: Number,
|
||||||
|
initialField: Object
|
||||||
|
},
|
||||||
|
data: function() {
|
||||||
|
return {
|
||||||
|
field: this.initialField
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
saveField: function(){
|
||||||
|
console.log(this.field)
|
||||||
|
// Update field in API
|
||||||
|
},
|
||||||
|
deleteField: function() {
|
||||||
|
// Delete field in API
|
||||||
|
this.$emit('delete-field', this.index);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<!-- You can't use index as :key here b/c Vue is crazy -->
|
||||||
|
<!-- https://rimdev.io/the-v-for-key/ -->
|
||||||
|
<div class="mb-5" v-for="(field, index) in fields" :key="field.id">
|
||||||
|
<Field
|
||||||
|
:index="index"
|
||||||
|
:initialField.sync="fields[index]"
|
||||||
|
@delete-field="deleteField"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="btn btn-sm btn-success btn-outlined float-right"
|
||||||
|
type="button"
|
||||||
|
@click="addField()"
|
||||||
|
>
|
||||||
|
Add New Field
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Field from "./Field.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "FieldList",
|
||||||
|
components: {
|
||||||
|
Field
|
||||||
|
},
|
||||||
|
props: {},
|
||||||
|
data: function() {
|
||||||
|
return {
|
||||||
|
fields: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
addField: function() {
|
||||||
|
this.fields.push({
|
||||||
|
id: `#${Math.random().toString(16).slice(2)}`,
|
||||||
|
name: "",
|
||||||
|
description: "",
|
||||||
|
editable: false,
|
||||||
|
required: false,
|
||||||
|
public: false
|
||||||
|
})
|
||||||
|
console.log(this.$data.fields)
|
||||||
|
},
|
||||||
|
deleteField: function(index) {
|
||||||
|
// if (fieldId) {
|
||||||
|
// Wait for API implementation
|
||||||
|
// }
|
||||||
|
// Remove field at index
|
||||||
|
this.fields.splice(index, 1);
|
||||||
|
console.log(this.fields)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.fields.push({
|
||||||
|
id: 1,
|
||||||
|
name: "Name",
|
||||||
|
description: "Desc",
|
||||||
|
editable: true,
|
||||||
|
required: false,
|
||||||
|
public: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@@ -9,6 +9,9 @@ import $ from "jquery";
|
|||||||
import { ezQuery, ezProgressBar, ezAlert } from "core/ezq";
|
import { ezQuery, ezProgressBar, ezAlert } from "core/ezq";
|
||||||
import CodeMirror from "codemirror";
|
import CodeMirror from "codemirror";
|
||||||
import "codemirror/mode/htmlmixed/htmlmixed.js";
|
import "codemirror/mode/htmlmixed/htmlmixed.js";
|
||||||
|
import Vue from "vue/dist/vue.esm.browser";
|
||||||
|
import Field from "../components/configs/fields/Field.vue";
|
||||||
|
import FieldList from "../components/configs/fields/FieldList.vue";
|
||||||
|
|
||||||
function loadTimestamp(place, timestamp) {
|
function loadTimestamp(place, timestamp) {
|
||||||
if (typeof timestamp == "string") {
|
if (typeof timestamp == "string") {
|
||||||
@@ -360,4 +363,10 @@ $(() => {
|
|||||||
$("#mail_username_password").toggle(this.checked);
|
$("#mail_username_password").toggle(this.checked);
|
||||||
})
|
})
|
||||||
.change();
|
.change();
|
||||||
|
|
||||||
|
// Insert CommentBox element
|
||||||
|
const fieldList = Vue.extend(FieldList);
|
||||||
|
let vueContainer = document.createElement("div");
|
||||||
|
document.querySelector("#user-field-list").appendChild(vueContainer);
|
||||||
|
new fieldList({}).$mount(vueContainer);
|
||||||
});
|
});
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -23,6 +23,9 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link rounded-0" href="#accounts" role="tab" data-toggle="tab">Accounts</a>
|
<a class="nav-link rounded-0" href="#accounts" role="tab" data-toggle="tab">Accounts</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link rounded-0" href="#fields" role="tab" data-toggle="tab">Custom Fields</a>
|
||||||
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link rounded-0" href="#mlc" role="tab" data-toggle="tab">MajorLeagueCyber</a>
|
<a class="nav-link rounded-0" href="#mlc" role="tab" data-toggle="tab">MajorLeagueCyber</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -61,6 +64,8 @@
|
|||||||
|
|
||||||
{% include "admin/configs/accounts.html" %}
|
{% include "admin/configs/accounts.html" %}
|
||||||
|
|
||||||
|
{% include "admin/configs/fields.html" %}
|
||||||
|
|
||||||
{% include "admin/configs/mlc.html" %}
|
{% include "admin/configs/mlc.html" %}
|
||||||
|
|
||||||
{% include "admin/configs/settings.html" %}
|
{% include "admin/configs/settings.html" %}
|
||||||
|
|||||||
24
CTFd/themes/admin/templates/configs/fields.html
Normal file
24
CTFd/themes/admin/templates/configs/fields.html
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<div role="tabpanel" class="tab-pane config-section" id="fields">
|
||||||
|
<form method="POST" autocomplete="off" class="w-100">
|
||||||
|
<h5>Custom Fields</h5>
|
||||||
|
|
||||||
|
<small class="form-text text-muted">
|
||||||
|
Add custom fields to get additional data from your participants
|
||||||
|
</small>
|
||||||
|
|
||||||
|
<ul class="nav nav-tabs mt-3" role="tablist">
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link active" href="#user-fields" role="tab" data-toggle="tab">
|
||||||
|
Users
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="tab-content">
|
||||||
|
<div role="tabpanel" class="tab-pane active" id="user-fields">
|
||||||
|
<div id="user-field-list" class="pt-3">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user