Jump to content

Kattes

uniGUI Subscriber
  • Posts

    144
  • Joined

  • Last visited

  • Days Won

    11

Posts posted by Kattes

  1. 39 minutes ago, Jean-Marc Kiener said:

    I would assume that the problem is the MySQL connection. You connect once on the server module. I would recommend to create a new connection every time you send a sql statement to the db. Also some dB connection components needs a coinitialize construct every time a connection is created.

    Hi Jean-Marc,

    So you would suggest to keep the DB connection in the state "connected := false" as long as I do not enter UniGUIServerModuleHTTPCommand routine - so changing its state here on entry to true and before leaving to false again?

  2. 13 minutes ago, Sherzod said:

    Hello,

    What is the response code gets a PHP app?

    The PHP App is fed with JSON strings in a normal case, which were triggered by the API calls coming from the PHP app. But sometimes it happens that an API call does not get any response. This status of not getting any responses can stay for some minutes up to an hour. But then its starting to work again, which is very strange.

  3. Hello,
    I am a bit clueless with a big problem I need to solve ASAP. The current situation is as followed. I am running on a Windows 2016 server two uniGui Applications. One works as a non visual DB server, which feeds an external PHP Shop Application with information like articles , prices, etc. The other one is a Backend  Application, which handles all the articles from the shop. So this behaves more like the standard uniGui Application we all know, using all the nice uniGui visual components we all love.

    overview.jpg.257aac685146f5c347d1b3670cabd3cc.jpg

    But my problem comes from the non visual application, which sometimes is not reachable, which means API calls from the PHP application do not get any response. Main part of this application is the Methode "UniGUIServerModuleHTTPCommand", which looks like this:
     

    procedure TUniServerModule.UniGUIServerModuleHTTPCommand(ARequestInfo: TIdHTTPRequestInfo;
      AResponseInfo: TIdHTTPResponseInfo; var Handled: Boolean);
    var
      sJSON, sParam, sRequest, s : string;
      i : integer;
      bValidRequest : boolean;
    begin
      // Examples of Supported APIs:
      // http://localhost:8077/v1/prom?ID=47       >> Get Details of selected event with the ID 47
      // http://localhost:8077/v1/Prom/CheckAvail  >> Check if server is online
      // http://localhost:8077/v1/Proms            >> Get List of current events
      bValidRequest := false;
    
      if pos('/v1', ARequestInfo.URI) = 1 then // API Call found !!
      begin
        AResponseInfo.ResponseNo := 200;
        Handled := True;
    
        if ARequestInfo.AuthExists and (ARequestInfo.AuthPassword='wshgdaizuddsfrtG12') and (ARequestInfo.AuthUsername='XCloud') then
        begin
          sRequest := Uppercase(ARequestInfo.URI);
          if  sRequest = Uppercase('/v1/Prom/CheckAvail') then
          // Checking the API accessibility during the purchase process
          begin
            bValidRequest := true;
            sJSON := '{"status": "online"}';
            AResponseInfo.ContentText := sJSON;
            LogPayServer('HTTP Request "CheckAvail"', sJSON);
          end;
    
          if sRequest=Uppercase('/v1/Proms') then
          // Returns a list of all currently active proms in JSON format.
          begin
            bValidRequest := true;
            sJSON := GetEventsAsJSON;
            LogPayServer('HTTP Request "Proms"', sJSON);
            AResponseInfo.ContentText := sJSON;
          end;
    
          if sRequest=Uppercase('/v1/Prom/OrderConfirmed') then
          // Called after the sales process has been completed
          begin
            sJSON := ARequestInfo.RawHeaders.Values['OrderInfo'];
            // Process received order information
            LogPayServer('HTTP Request "OrderConfirmed"', sJSON);
            if AddJsonOrderInformationToDB2(sJSON) then
            begin
              LogPayServer('HTTP Request "OrderConfirmed"', 'bValidRequest=true');
              bValidRequest := true;
              AResponseInfo.ContentText := '{"status": "processed"}'; // if everything is OK, than return follwing:
            end
            else
              LogPayServer('HTTP Request "OrderConfirmed"', 'bValidRequest=false');
          end;
    
          if sRequest=Uppercase('/v1/Prom') then
          begin
            sParam := ARequestInfo.Params.Values['VoucherVal'];
            // Request to check the value of the given voucher
            if sParam <>'' then
            begin
              bValidRequest := true;
              // Get from DB the value of the given voucher and return it to JSON
              sJSON := '{"voucher value": '+GetVoucherValue(ZConnectionServerModule, sParam)+'}';
              AResponseInfo.ContentText := sJSON;
              LogPayServer('HTTP Request "VoucherVal" ('+sParam+')', sJSON);
            end;
    
            sParam := ARequestInfo.Params.Values['Id'];
            // Returns information of the event, which was selected via its Id
            if sParam <>'' then
            begin
              bValidRequest := true;
              sJSON := GetEventDetailsJSON(sParam);
              AResponseInfo.ContentText := sJSON;
              LogPayServer('HTTP Request "Prom?Id=?"', sJSON);
            end;
          end;
          if not bValidRequest then
          begin
            AResponseInfo.ContentText := '<html>Not supported API-Call; Please check API documentation!</html>';
            LogPayServer('HTTP Request "API ERROR"', ARequestInfo.URI);
          end;
        end
        else
        begin
          AResponseInfo.ContentText := '<html>Wrong or missing PW; Please use Basic Auth!</html>';
          LogPayServer('HTTP Request "Invalid Caller"', 'PW / Auth wrong');
        end;
      end;
    end;

     

    The Internalisation Methode is also simple and straightforward: 

    procedure TUniServerModule.UniGUIServerModuleCreate(Sender: TObject);
    begin
      sHTML1 := tStringList.Create;
      sHTML2 := tStringList.Create;
      with ZConnectionServerModule do
      begin
        Connected := False;
        LibraryLocation := StartPath+'files\dll\libmysql.dll';
        Protocol := 'mysql';
        HostName := 'localhost';
        Port := 3306;
        Database := 'xxxxx';
        User := 'root';
        Password := '-----';
        Connected := true;
      end;
      LogPayServer('UniGUIServerModuleCreate','Server V'+FileVersionGet(StartPath+'AbiPaymentServer.dll')+' Created and running');
    end;

    I am mentioning it here because as you can see it also uses a Log-Call, which writes information to a log table within my MySQL database and I can find randomly entries in the log, which show me that the application was restarted.

    At the moment the traffic handled by this Application is very low (less than 10 API calls per hour). Nevertheless I have the problem that the Application does not response and is not reachable sometimes. This is something I have not seen as long as I used it as standalone Application.

    Any comments or help are more than welcome!

  4. But don not waste too much of your time on it. I also found a different solution which is suitable for me .

    unit Main;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics,
      Controls, Forms, uniGUITypes, uniGUIAbstractClasses,
      uniGUIClasses, uniGUIRegClasses, uniGUIForm, uniPanel, uniGUIBaseClasses,
      uniButton, Vcl.Imaging.jpeg, uniImage, uniEdit, uniSpinEdit;
    
    type
      TMainForm = class(TUniForm)
        UniButton1: TUniButton;
        UniPanel1: TUniPanel;
        UniImage1: TUniImage;
        UniEdit1: TUniEdit;
        UniEdit2: TUniEdit;
        UniSpinEdit1: TUniSpinEdit;
        procedure UniButton1Click(Sender: TObject);
      private
        { Private declarations }
        bToggle : boolean;
      public
        { Public declarations }
      end;
    
    function MainForm: TMainForm;
    
    implementation
    
    {$R *.dfm}
    
    uses
      uniGUIVars, MainModule, uniGUIApplication;
    
    procedure FadeInOut(xControl: TUniControl; bFadeOut: boolean; const Duration : integer = 300);
    begin
      if bFadeOut then
        xControl.JSInterface.JSCode(#1'.el.fadeOut({duration: '+IntToStr(Duration)+'});')
      else
        xControl.JSInterface.JSCode(#1'.el.fadeIn({duration: '+IntToStr(Duration)+'});')
    end;
    
    function MainForm: TMainForm;
    begin
      Result := TMainForm(UniMainModule.GetFormInstance(TMainForm));
    end;
    
    procedure TMainForm.UniButton1Click(Sender: TObject);
    begin
      bToggle :=  not bToggle;
      FadeInOut(UniPanel1, bToggle, UniSpinEdit1.Value);
      FadeInOut(UniImage1, bToggle, UniSpinEdit1.Value);
    end;
    
    initialization
      RegisterAppFormClass(TMainForm);
    end.

    image.png.ea934d608537dc7f4308d416cc169eff.png

  5. Hi,
    I have a little problem to get a UniPanel "fadeOut" when changing its property "visible" from true to false - the other direction (fadeIn) works fine.

    Fade in is programmed as followed:

    UniPanelStatus.ClientEvents.ExtEvents.Add('show=function show(sender, eOpts){'+
                                                 'sender.el.setOpacity(0); '+
                                                 'sender.el.fadeIn({duration: 500});'+
                                                 '}'
                                               );

    How has  a valid solution for "fadeOut" look like?

    I tried the following without success:

    UniPanelStatus.ClientEvents.ExtEvents.Add('hide=function hide(sender, eOpts){'+
                                                 'sender.el.setOpacity(1); '+
                                                 'sender.el.fadeOut({duration: 500});'+
                                                 '}'
                                              );

     

  6. On 1/15/2020 at 10:50 AM, Freeman35 said:

    Hello,

    https://stackoverflow.com/questions/29292596/save-load-objects-as-blob-in-a-database

    If I were you, I'm not save file to db. Make a folder, (I have not new version unigui) fileupload component saving file on server side. After saved this file move & rename it. then transfer file that from folder. Just save name and path to db. This is much better way.

    regards.

    I totally agree to Freeman35's post - Putting big files into a database makes everything slow and a backup of such a huge DB can become a nightmare!
    As already recommended, please put only file references to the DB.

  7. Thank you Sherzod!

    I slightly modified the solution you sent me, which I also want to share with the community.

    procedure HideMenueItems(var MyTreeMenu: TUniTreeMenu; const sHide: string);
    var
      s,sH : string;
      i : integer;
      llist: string;
    begin
      llist := '';
      sH := ','+sHide+',';
      for i := 0 to MyTreeMenu.Items.Count-1 do
      begin
        s := ','+MyTreeMenu.Items[i].AttachedMenuItem.Caption+',';
        if pos(s, sH)>0  then
        begin
          MyTreeMenu.Items[i].AttachedMenuItem.Visible := false;
          if llist='' then llist := '"'+MyTreeMenu.Items[I].AttachedMenuItem.Caption+'"'
             else llist := llist + ',"' + MyTreeMenu.Items[I].AttachedMenuItem.Caption+'"';
        end;
      end;
      if llist<>'' then
      begin
        MyTreeMenu.JSInterface.JSAssign('_rtext', [MyTreeMenu.JSControl.JSArray(llist)]);
        MyTreeMenu.JSInterface.JSCode('var me='#1';'+
          'if(me._rtext) me.getStore().each(function(record) {'+
          '    if (me._rtext.indexOf(record.get("text")) > -1) {'+
          '        record.remove()'+
          '    }'+
          '});'
        );
      end;
    end;
    
    procedure TMainForm.UniButtonHideClick(Sender: TObject);
    begin
      HideMenueItems(UniTreeMenu, 'Dashboard,Database,Management,Customers');
    end;

     

    • Like 1
  8. Actually my approach is not relevant here, but I can of course tell you how I did it:

    I simply created in my MySQL DB a table view, which contained a field:

    Concat('<progress max="100" value="',Progr,'">',Progr,'%</progress>') as  progress

    This made the trick for me. But I am more interested in the widget approach, because it is using pre-defined themes and will look for browsers equal.

  9. Sorry but I also have problems using your solutions. 

    I have the following uniTreeMenu structure: 

    image.png.1cda29dcccf4adb5be31dcc92cf1f98e.png

    .. and want to hide menu items "Management" and its children for "simple" users.

    Therefor I am using the following code:

    procedure TuDashboardFrame.UniPanelLoginClick(Sender: TObject);
    var
      s : string;
      i : integer;
    begin
      with MainForm do
      begin
        for i := 0 to UniTreeMenu1.Items.Count-1 do
        begin
         s := UniTreeMenu1.Items[i].AttachedMenuItem.Caption;
         if pos(s, 'Database Management Customers')>0  then
           UniTreeMenu1.Items[i].AttachedMenuItem.Visible := false;
        end;
        UpdateTreeMenu(UniTreeMenu1);
      end;
    end;

    in combination with your slightly adapted solution:

    procedure UpdateTreeMenu (myMenu : TUniTreeMenu);
    var
      I: Integer;
      _llist: string;
    begin
      with myMenu do
      begin
        SourceMenu.Items[0].Visible := False;
        _llist := '';
        for I := 0 to SourceMenu.Items.Count-1 do
          if not SourceMenu.Items[I].Visible then
            if _llist='' then _llist := '"'+SourceMenu.Items[I].Caption+'"'
            else _llist := _llist + ',"' + SourceMenu.Items[I].Caption+'"';
        if _llist<>'' then
        begin
          JSInterface.JSCall('getStore().clearFilter', []);
          JSInterface.JSCode(#1'.getStore().filterBy(function (record){ if (['+ _llist +'].indexOf(record.get("text"))>-1) return false; else return true;});');
        end
        else
          JSInterface.JSCall('getStore().clearFilter', []);
      end;
    end;

    Unfortunately this is not working :(

  10. OK, I got it working, but the example (\FMSoft\Framework\uniGUI\Demos\Desktop\Grid - WidgetColumn2) is not really self explaining.

    The screen shot below is using ProgressWidget (column Progr) and some HTML hard coded solution from me (column Progress).

    Question: Is there a way to center the widget vertically? I tried it using margins, but that does not seem to work.

    image.png.955edb65c2e4c49153bdab93200ace49.png

     

  11. I know this is a really old topic, but I need to inform you that current solutions has problems. In one of my applications I am using a uniDBGrid to visualize different DB tables. Based on the above examples I tried to assign different page sizes based on the selected table.

    Therefore I used this modified routine:

    procedure TuDBFrame.SetPageSize(PageSize : integer);
    var
      DBGridJSName: string;
      RecordCount: Integer;
      JSCode: string;
      st : TDataSetState;
    begin
      DBGridJSName := UniDBGrid.JSName;
      st := UniDBGrid.DataSource.DataSet.State;
      if st in [dsInactive] then
        UniDBGrid.DataSource.DataSet.Open;
      RecordCount := UniDBGrid.DataSource.DataSet.RecordCount;
      UniDBGrid.WebOptions.PageSize := PageSize;
    
      JSCode := DBGridJSName + '.getStore().pageSize=' + IntToStr(PageSize) + ';';
      if RecordCount > PageSize then
        JSCode := JSCode + DBGridJSName + '.pagingBar.show();'
      else
        JSCode := JSCode + DBGridJSName + '.pagingBar.hide();';
    
      JSCode := JSCode + DBGridJSName + '.getStore().load();';
      UniSession.AddJS(JSCode);
    end;

    If I call this routine the first time for e.g. table A with a PageSize of 50 records and later for a different table B with a PageSize of 100 only the first 50 records of table B are listed in the dbgrid on the first page, i.e. 50 records are lost on the first page! When switching to the second page, this starts with record number 101 (which is in line with the changed page size).

    I guess that the first call changes also some unknown but important JS variable, which later will not get changed anymore and leads to this unwanted effect.

  12. Great - Thank you for the fast reply!

    This is really fantastic and makes my life much easier. So far I wasn't aware of that in case of using IIS with ISAPI no PEM files are needed - probably I have simply overseen it.

    Best  regards,
    Carsten

    • Like 1
×
×
  • Create New...