Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Events - uAdmin based application #45

Closed
MarErm27 opened this issue Jan 23, 2020 · 30 comments
Closed

Events - uAdmin based application #45

MarErm27 opened this issue Jan 23, 2020 · 30 comments
Labels
help wanted Extra attention is needed

Comments

@MarErm27
Copy link
Contributor

Hello! I'm doing my first apllication based on uAdmin. When I'm trying to open model Kit I got this Error: https://play.golang.org/p/hsENK7L0f2U

Project: https://github.com/MarErm27/Events

@rn1hd
Copy link
Collaborator

rn1hd commented Jan 23, 2020

Good day! Two errors are found in kit.go:
1.) The first letter of nomenclatureID field in kit.go is not capitalized. It should be NomenclatureID.
2.) There should be a closing apostrophe on the uadmin tags in CostInKit field. `uadmin:"money;pattern:^[0-9]*$;pattern_msg:Your input must be a number.;help:Input numeric characters only in this field."`

Now test your application to see if it will work.

@MarErm27
Copy link
Contributor Author

It' perfect! You are the best! @Spotlight64

@rn1hd
Copy link
Collaborator

rn1hd commented Jan 23, 2020

My pleasure.

@MarErm27
Copy link
Contributor Author

MarErm27 commented Jan 24, 2020

I'm trying to make a calculated field sum which is a product of quantity and price in a model Menu.
image
So when I change price or quantity my sum field has to become changed.

My desire is to be able to do something like this.
image

Here number and cost can call a javascript onChange event. So here what javascripts may contain.

numberOnChangeScript.js contains this:

document.getElementsByName("Number")[0].onchange = function(){
document.getElementsByName("Sum")[0].value = document.getElementsByName("Number")[0].value * document.getElementsByName("Cost")[0].value
}

costOnChangeScript.js contains this:

document.getElementsByName("Cost")[0].onchange = function(){
document.getElementsByName("Sum")[0].value = document.getElementsByName("Number")[0].value * document.getElementsByName("Cost")[0].value
} 

@Spotlight64 may it be already possible to do but I just don't know how to? Please, help me

@rn1hd
Copy link
Collaborator

rn1hd commented Jan 25, 2020

Yes, it is possible. Inside the static folder, create a folder named js and inside it, create a Javascript file (e.g. "form.js") with the following codes below:

(function(win, doc, $){
	"using strict";

	$(doc).ready(function(){
		var number = $("input[name='Number']");
		var cost = $("input[name='Cost']");
		var sum = $("input[name='Sum']");

		number.on("keyup", function(){
			sum.val(number.val() * cost.val());
		});

		cost.on("keyup", function(){
			sum.val(number.val() * cost.val());
		});
	});
})(window, document, $);

In your main.go, use IncludeFormJS method to apply the changes in the form. Now the value of the Sum will automatically recompute in the form once you change either the Number or Cost value in real time.

// Call the ModelName schema of "menu" model
menu := uadmin.Schema["menu"]

// Include Javascript file for the form
menu.IncludeFormJS = []string{"/static/js/form.js"}

// Pass back the menu variable to apply changes
uadmin.Schema["menu"] = menu

And in the menu.go, you can solve it after you save the record by implementing some calculation inside the Save function.

func (m *Menu) Save() {
	// Multiply the Number and the Cost to get the value of the Sum
	m.Sum = m.Number * m.Cost
	uadmin.Save(m)
}

You can check this page for more examples on manipulating ModelSchema: https://uadmin-docs.readthedocs.io/en/latest/api/modelschema.html#uadmin-modelschema

@MarErm27
Copy link
Contributor Author

This is great! Thank you a lot!
For your information, it says there is a error but nothing seems to me broken:
image
image
FireFox browser

@rn1hd
Copy link
Collaborator

rn1hd commented Jan 25, 2020

You are welcome. Regarding the error, it's a minor issue from the source code in fact that nothing affects in the user side. Nonetheless, we will fix that error as soon as possible.

Thanks for reporting.

@dxlvgcw
Copy link

dxlvgcw commented Jan 25, 2020

@Spotlight64 I also saw many errors on console when I load uAdmin dashboard. everything seems fine but no error at all is better.
Untitled

@rn1hd
Copy link
Collaborator

rn1hd commented Jan 25, 2020

Well noted, thanks

@MarErm27
Copy link
Contributor Author

Menu table is a child of an event named "first Event". Can I edit this table directly in the list form? Can I make sure that the table summary row is always at the bottom and how do I fill it in? Can I put my Menu table inside the Event model?
image

@MarErm27
Copy link
Contributor Author

MarErm27 commented Jan 29, 2020

Hello! Have a great day @Spotlight64
I've been trying to find a way to solve my task. Based on the way that you showed me for menu model I've added this editable table from Bootstrap https://mdbootstrap.com/docs/jquery/tables/editable/

I've noticed that when I change my js files they are getting cashed - when I restart uAdmin in Visual Studio Code and restart my browser I'm getting previous version of js script. Have you noticed it? How do you solve it?

I'm going to change columns of this table to fit my data and I'm going to make an Ajax request when the event is getting saved to make records in menu model. I'm also going to make an Ajax request when I open the event model to load previously made records with this table. I'm not sure if there is a way to load the table with data at same time when I load the model.

I will be very grateful for any tips and advices.

Here is my "/static/js/eventForm.js" file.

var e = document.getElementById("Event")
menuTable = '<!-- Editable table -->\
<div class="card">\
  <h3 class="card-header text-center font-weight-bold text-uppercase py-4">Editable table</h3>\
  <div class="card-body">\
    <div id="table" class="table-editable">\
      <span class="table-add float-right mb-3 mr-2"><a href="#!" class="text-success"><i\
            class="fas fa-plus fa-2x" aria-hidden="true"></i></a></span>\
      <table class="table table-bordered table-responsive-md table-striped text-center">\
        <thead>\
          <tr>\
            <th class="text-center">Person Name</th>\
            <th class="text-center">Age</th>\
            <th class="text-center">Company Name</th>\
            <th class="text-center">Country</th>\
            <th class="text-center">City</th>\
            <th class="text-center">Sort</th>\
            <th class="text-center">Remove</th>\
          </tr>\
        </thead>\
        <tbody>\
          <tr>\
            <td class="pt-3-half" contenteditable="true">Aurelia Vega</td>\
            <td class="pt-3-half" contenteditable="true">30</td>\
            <td class="pt-3-half" contenteditable="true">Deepends</td>\
            <td class="pt-3-half" contenteditable="true">Spain</td>\
            <td class="pt-3-half" contenteditable="true">Madrid</td>\
            <td class="pt-3-half">\
              <span class="table-up"><a href="#!" class="indigo-text"><i class="fas fa-long-arrow-alt-up"\
                    aria-hidden="true"></i></a></span>\
              <span class="table-down"><a href="#!" class="indigo-text"><i class="fas fa-long-arrow-alt-down"\
                    aria-hidden="true"></i></a></span>\
            </td>\
            <td>\
              <span class="table-remove"><button type="button"\
                  class="btn btn-danger btn-rounded btn-sm my-0">Remove</button></span>\
            </td>\
          </tr>\
          <!-- This is our clonable table line -->\
          <tr>\
            <td class="pt-3-half" contenteditable="true">Guerra Cortez</td>\
            <td class="pt-3-half" contenteditable="true">45</td>\
            <td class="pt-3-half" contenteditable="true">Insectus</td>\
            <td class="pt-3-half" contenteditable="true">USA</td>\
            <td class="pt-3-half" contenteditable="true">San Francisco</td>\
            <td class="pt-3-half">\
              <span class="table-up"><a href="#!" class="indigo-text"><i class="fas fa-long-arrow-alt-up"\
                    aria-hidden="true"></i></a></span>\
              <span class="table-down"><a href="#!" class="indigo-text"><i class="fas fa-long-arrow-alt-down"\
                    aria-hidden="true"></i></a></span>\
            </td>\
            <td>\
              <span class="table-remove"><button type="button"\
                  class="btn btn-danger btn-rounded btn-sm my-0">Remove</button></span>\
            </td>\
          </tr>\
          <!-- This is our clonable table line -->\
          <tr>\
            <td class="pt-3-half" contenteditable="true">Guadalupe House</td>\
            <td class="pt-3-half" contenteditable="true">26</td>\
            <td class="pt-3-half" contenteditable="true">Isotronic</td>\
            <td class="pt-3-half" contenteditable="true">Germany</td>\
            <td class="pt-3-half" contenteditable="true">Frankfurt am Main</td>\
            <td class="pt-3-half">\
              <span class="table-up"><a href="#!" class="indigo-text"><i class="fas fa-long-arrow-alt-up"\
                    aria-hidden="true"></i></a></span>\
              <span class="table-down"><a href="#!" class="indigo-text"><i class="fas fa-long-arrow-alt-down"\
                    aria-hidden="true"></i></a></span>\
            </td>\
            <td>\
              <span class="table-remove"><button type="button"\
                  class="btn btn-danger btn-rounded btn-sm my-0">Remove</button></span>\
            </td>\
          </tr>\
          <!-- This is our clonable table line -->\
          <tr class="hide">\
            <td class="pt-3-half" contenteditable="true">Elisa Gallagher</td>\
            <td class="pt-3-half" contenteditable="true">31</td>\
            <td class="pt-3-half" contenteditable="true">Portica</td>\
            <td class="pt-3-half" contenteditable="true">United Kingdom</td>\
            <td class="pt-3-half" contenteditable="true">London</td>\
            <td class="pt-3-half">\
              <span class="table-up"><a href="#!" class="indigo-text"><i class="fas fa-long-arrow-alt-up"\
                    aria-hidden="true"></i></a></span>\
              <span class="table-down"><a href="#!" class="indigo-text"><i class="fas fa-long-arrow-alt-down"\
                    aria-hidden="true"></i></a></span>\
            </td>\
            <td>\
              <span class="table-remove"><button type="button"\
                  class="btn btn-danger btn-rounded btn-sm my-0">Remove</button></span>\
            </td>\
          </tr>\
        </tbody>\
      </table>\
    </div>\
  </div>\
</div>\
<!-- Editable table -->'
e.innerHTML += menuTable
const $tableID = $('#table');
 const $BTN = $('#export-btn');
 const $EXPORT = $('#export');

 const newTr = `
<tr class="hide">
  <td class="pt-3-half" contenteditable="true">Example</td>
  <td class="pt-3-half" contenteditable="true">Example</td>
  <td class="pt-3-half" contenteditable="true">Example</td>
  <td class="pt-3-half" contenteditable="true">Example</td>
  <td class="pt-3-half" contenteditable="true">Example</td>
  <td class="pt-3-half">
    <span class="table-up"><a href="#!" class="indigo-text"><i class="fas fa-long-arrow-alt-up" aria-hidden="true"></i></a></span>
    <span class="table-down"><a href="#!" class="indigo-text"><i class="fas fa-long-arrow-alt-down" aria-hidden="true"></i></a></span>
  </td>
  <td>
    <span class="table-remove"><button type="button" class="btn btn-danger btn-rounded btn-sm my-0 waves-effect waves-light">Remove</button></span>
  </td>
</tr>`;

 $('.table-add').on('click', 'i', () => {

   const $clone = $tableID.find('tbody tr').last().clone(true).removeClass('hide table-line');

   if ($tableID.find('tbody tr').length === 0) {

     $('tbody').append(newTr);
   }

   $tableID.find('table').append($clone);
 });

 $tableID.on('click', '.table-remove', function () {

   $(this).parents('tr').detach();
 });

 $tableID.on('click', '.table-up', function () {

   const $row = $(this).parents('tr');

   if ($row.index() === 1) {
     return;
   }

   $row.prev().before($row.get(0));
 });

 $tableID.on('click', '.table-down', function () {

   const $row = $(this).parents('tr');
   $row.next().after($row.get(0));
 });

 // A few jQuery helpers for exporting only
 jQuery.fn.pop = [].pop;
 jQuery.fn.shift = [].shift;

 $BTN.on('click', () => {

   const $rows = $tableID.find('tr:not(:hidden)');
   const headers = [];
   const data = [];

   // Get the headers (add special header logic here)
   $($rows.shift()).find('th:not(:empty)').each(function () {

     headers.push($(this).text().toLowerCase());
   });

   // Turn all existing rows into a loopable array
   $rows.each(function () {
     const $td = $(this).find('td');
     const h = {};

     // Use the headers from earlier to name our hash keys
     headers.forEach((header, i) => {

       h[header] = $td.eq(i).text();
     });

     data.push(h);
   });

   // Output the result
   $EXPORT.text(JSON.stringify(data));
 });

@rn1hd rn1hd added the help wanted Extra attention is needed label Jan 29, 2020
@dxlvgcw
Copy link

dxlvgcw commented Jan 29, 2020

@MarErm27 I am not sure why saving crashes on your side. Javascript files are used to change something in the form and list which I find it working but if you want to update the records in your custom table that links to your Menu table inline, you need to do it in Go.

@alphakitchown Somehow you have a way to this one?

@MarErm27
Copy link
Contributor Author

MarErm27 commented Jan 29, 2020

@MarErm27 I am not sure why saving crashes on your side. Javascript files are used to change something in the form and list which I find it working but if you want to update the records in your custom table that links to your Menu table inline, you need to do it in Go.

@alphakitchown Somehow you have a way to this one?

@dxlvgcw I clean cache for localhost:8080 in browser settings. It is works. But this is not a best way because I will have to clean cache on each computer after each update of JS file.

@alphakitchown
Copy link

from my research, i saw three functions in uadmin that automatically clears cache when you update something. its not those ones that solve javascript issue unfortunately

@dxlvgcw
Copy link

dxlvgcw commented Jan 29, 2020

We can request a feature for Javascript file support.

@MarErm27
Copy link
Contributor Author

MarErm27 commented Jan 29, 2020

@dxlvgcw I'm trying to impement a table in model Events which is a parent of model Menu. I want to load all records of model Menu where parent of each model is Event and put it to the custom table made by JavaScirpt on the page of Event model. The table is editable and when changes are done I need to record all changes to Menu model. I hope this will explain better what I'm trying to do, sorry for my english

@dxlvgcw
Copy link

dxlvgcw commented Jan 29, 2020

Okey I get what you mean. I will solve that one as much as I can.

@dxlvgcw
Copy link

dxlvgcw commented Jan 31, 2020

@alphakitchown Hello! This is really difficult for me. Can you help me solve this problem?

@alphakitchown
Copy link

@dxlvgcw i find it very challenging too. playing around with uadmin forms from what i know is beyond my knowledge already.

just want to give you a hype, one of uadmin developers share a sneak peek of upcoming read the docs

@dxlvgcw
Copy link

dxlvgcw commented Jan 31, 2020

Really? Then this is good news!!!

@MarErm27
Copy link
Contributor Author

MarErm27 commented Feb 8, 2020

Hello! I'm trying to fetch all Menu model records with specified EventId where EventId is a field of model Event with this code:

menu := []models.Menu{}
uadmin.AdminPage("id", false, 0, 100, &menu, "EventID = ?", 1)
for m := range menu {
	uadmin.Preload(&menu[m])
}
uadmin.ReturnJSON(w, r, menu)

I got error "no such column: EventID "

Menu model struct

//Menu for event document !
type Menu struct {
	uadmin.Model
	Name           string
	Event          Event
	EventID        uint
	Nomenclature   Nomenclature
	NomenclatureID uint
	Number         int `uadmin:"min:1"`
	Cost           int `uadmin:"money;pattern:^[0-9]*$;pattern_msg:Your input must be a number.;help:Input numeric characters only in this field."`
	Sum            int `uadmin:"read_only"`
	Kit            Kit
	KitID          uint
}

Event model struct

//Event document !
type Event struct {
	uadmin.Model
	Name              string
	Counterparty      Counterparty
	CounterpartyID    uint
	Contract          Contract
	ContractID        uint
	Places            Places
	PlacesID          uint
	TypesOfDiscount   TypesOfDiscount
	TypesOfDiscountID uint
	Discount          int
	Folder            Folder `uadmin:"filter"`
	FolderID          uint
	CreatedDate       time.Time
	Channel           Channel `uadmin:"list_exclude"`
	ChannelID         uint
	CreatedBy         string
}

How to fetch all Menu model records with specified EventId?

@rn1hd
Copy link
Collaborator

rn1hd commented Feb 8, 2020

Good day! Use uadmin.Filter to fetch all records. Replace EventID to event_id, so it will be like this:
uadmin.Filter(&menu, "event_id = ?", 1)

@MarErm27
Copy link
Contributor Author

MarErm27 commented Feb 8, 2020

@Spotlight64 Thank you so much!

@MarErm27
Copy link
Contributor Author

MarErm27 commented Feb 9, 2020

Hello!
An interesting note: once I added AJAX request my .js don't cash anymore.
image
It is not finished.
According to this tutorial https://uadmin-docs.readthedocs.io/en/latest/tutorial/part8.html
I've added an API for tables located at http://localhost:8080/api/table.

package api

import (
	"fmt"
	"net/http"
	"strings"

	// Specify the username that you used inside github.com folder
	"github.com/MarErm27/Events/models"
	//"github.com/MarErm27/Events/models"
	"github.com/uadmin/uadmin"
)

// TableHandler !
func TableHandler(w http.ResponseWriter, r *http.Request) {
	// r.URL.Path creates a new path called /todo_list
	r.URL.Path = strings.TrimPrefix(r.URL.Path, "/table")

	switch r.Method {
	case "GET":
		//http.ServeFile(w, r, "form.html")
		host := string(r.Host)
		referer := r.Header["Referer"][0]
		hostIndex := strings.Index(referer, host)
		modelNameIndex := hostIndex + len(host) + len(uadmin.RootURL)
		refererSubStringAfterModelNameIndex := referer[modelNameIndex:]
		modelNameLastIndex := strings.Index(refererSubStringAfterModelNameIndex, "/")
		modelName := refererSubStringAfterModelNameIndex[:modelNameLastIndex]
		switch modelName {
		case "event":
			//menu := []models.["modelName"]{}
			// Assigns a map as a string of interface to store any types of values
			results := []map[string]interface{}{}
			// Fetches all object in the database
			menu := []models.Menu{}
			eventIDToGet := refererSubStringAfterModelNameIndex[modelNameLastIndex+1:]
			uadmin.Filter(&menu, "event_id = ?", eventIDToGet)

			// Accesses and fetches data from another model
			for i := range menu {
				uadmin.Preload(&menu[i])
				// Assigns the string of interface in each Todo fields
				results = append(results, map[string]interface{}{
					// This returns only the name of the Category model, not the
					// other fields
					"Nomenclature": menu[i].Nomenclature.Name,
					// This returns only the name of the Friend model, not the
					// other fields
					"Number": menu[i].Number,
					// This returns only the name of the Item model, not the other
					// fields
					"Cost":        menu[i].Cost,
					"Sum":         menu[i].Sum,
					"Kit":         menu[i].Kit.Name,
					"Description": menu[i].Description,
				})
			}

			// Prints the todo in JSON format
			uadmin.ReturnJSON(w, r, results)
		default:
			fmt.Fprintf(w, "Sorry, there is no table for this model specified.")
		}
	case "POST":
		//Call ParseForm() to parse the raw query and update r.PostForm and r.Form.
		if err := r.ParseForm(); err != nil {
			fmt.Fprintf(w, "ParseForm() err: %v", err)
			return
		}
		fmt.Fprintf(w, "Post from website! r.PostFrom = %v\n", r.PostForm)
		name := r.FormValue("name")
		address := r.FormValue("address")
		fmt.Fprintf(w, "Name = %s\n", name)
		fmt.Fprintf(w, "Address = %s\n", address)

		//case method is get nomenclature list - get nomenclature for dropdown menu in a table
	default:
		fmt.Fprintf(w, "Sorry, only GET and POST methods are supported.")
	}
}

I do AJAX GET request here.

 var dataFromAjax
 $.ajax({
    url: "http://localhost:8080/api/table",
    method: "GET",
    //data : { sendedData: 'Hello'},
     success : function(data) {
        alert(data);
        dataFromAjax = data;
        var result = JSON.parse(dataFromAjax);
        rov1 = $(document).find('#table').find('tr')[1].children;
        for (let i = 0; i < result.length; i++) {
          console.log(i);
          if (i == 0) {
            for (let j = 0; j < rov1.length; j++) {
              console.log(rov1[j].value);
            }
          }
        }
    },
  });

It is goes to http://localhost:8080/api/table and it returns all records with parent of a current event.
I'm trying to fill the table. First column is Nomenclature type of model Nomenclature. This model may contains thousands of records and because of that I'm trying to add a dropdown list with filter. So when you type a name of a nomenclature that you are interested in you get list of nomenclatures with similar names. I'm trying but I don't know how to do it. I'm also don't know how to set a value of it.
image
Here is the code of a dropdown list with filter:

<td class="pt-3-half" <div class="container">\
           <div class="dropdown">\
             <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Nomenclature\
             <span class="caret"></span></button>\
             <ul class="dropdown-menu">\
               <input class="form-control" id="myInput" type="text" placeholder="Search..">\
               <li><a href="#">Crisps</a></li>\
               <li><a href="#">Cola</a></li>\
               <li><a href="#">Burger</a></li>\
             </ul>\
           </div>\
         </div>\
         <script>\
         $(document).ready(function(){\
           $("#myInput").on("keyup", function() {\
             var value = $(this).val().toLowerCase();\
             $(".dropdown-menu li").filter(function() {\
               $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1)\
             });\
           });\
         });\
         </script>\
</td>\

I'm stuck with this dropdown list with filter. I was wondering if you might be able to help. Please

@dxlvgcw
Copy link

dxlvgcw commented Feb 11, 2020

@alphakitchown @Spotlight64 Let's unite together to solve this!

@alphakitchown
Copy link

@dxlvgcw solving this challenge on our own is near to impossible unless you are going to modify the source code on the form itself.

as far as i know, apis are designed for your templates. you can modify the admin page by using uadmin functions. else, modify the source code but we cannot because it already violates computer ethics. best solution is we should request the uadmin developers this feature to include it as soon as possible

we hope anyone who is more knowledgeable than us can help using the tools they have now.

@dxlvgcw
Copy link

dxlvgcw commented Feb 12, 2020

I still think it is possible. You just need to be dedicated to this until you find out the solution to the problem. Just feel like you are in the laboratory trying to find out the cure of 2019-nCOV. It does not matter whether it will take us one week, two weeks, or even one month. What really matters is it does not cache Javascript file. This is what we need to ask the developers of uadmin.

@alphakitchown
Copy link

alphakitchown commented Feb 13, 2020

this challenge is pretty easy if you are working on your templates. there are many strange situations when i work it on the admin page. this is why modifying the source code would be the best action

go to templates > uadmin > default. open the html files inside. you will understand my point

@uadmin
Copy link
Owner

uadmin commented Jul 28, 2020

I think we you might be trying to reimplement inlines?

https://uadmin-docs.readthedocs.io/en/latest/api/register_functions.html#uadmin-registerinlines

@uadmin
Copy link
Owner

uadmin commented Jul 30, 2020

If there is more to this issue please feel free to reopen it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

5 participants