Telerik Forums
UI for ASP.NET MVC Forum
7 answers
1.1K+ views
is it possible to have the pagination on top and bottom of the grid?  today it always sits at the bottom but on our case where the list is big, it would be nice to have it on top so use don't have to navigate to the bottom for pagination.  Thanks.
Laurie
Top achievements
Rank 2
 answered on 22 May 2015
4 answers
2.2K+ views

Hi Guys,

I have a custom button in a nested grid. I want when the user clicks the button to download a file  saved in my database and save it to the local disk.

Whats the best approach? And could you provide a sample of how to call the controller action for download, how to pass ASSIGNMENT_DOCUMENT_ID, and after returning the file from the controller to ask the user where to save it? Not sure how to do post and get or do I need to do a get with the custom button..

Here is my nested grid:

@using PartnerLink.Models
@using Telerik.OpenAccess.SPI
@model Tuple<TBL_ASSIGNMENT, IQueryable<TBL_ASSIGNMENT_EXPENDITURE_VALUE>, IQueryable<TBL_ASSIGNMENT_INCOME_VALUE>, IQueryable<TBL_ASSIGNMENT_VEHICLE>>
 
<div style="height:500px">
    @(Html.Kendo().Grid<AssignmentDocTypesExt>()
        .Name("gridCaseDocuments")
        .Columns(columns =>
        {
            columns.Bound(p => p.ASSIGNMENT_DOCUMENT_TYPE_ID).Hidden(true);
            columns.Bound(p => p.ASSIGNMENT_ID).Hidden(true);
            columns.Bound(p => p.DOCUMENT_TYPE_ID).Hidden(true);
            columns.Bound(p => p.WHICH_APPLICANT).Hidden(true);
            columns.Bound(p => p.DOCUMENT_TYPE_STATUS_ID).Hidden(true);
            columns.Bound(p => p.CREDITOR_ID).Hidden(true);
            columns.Bound(p => p.numOfUploadedFiles).Hidden(true);
            columns.Bound(p => p.documentDescription).Title("Document").Width(350);
            columns.Bound(p => p.whichApplicant).Title("Applicant").Width(100);
            columns.Bound(p => p.documentTypeStatusDescription).Title("Type Status").Width(200);          
            columns.Bound(p => p.COMPLETE_FLAG).Title("Complete").ClientTemplate("<input type='checkbox' #= COMPLETE_FLAG ? checked='checked' :'' # disabled />").Width(90);
            columns.Bound(p => p.autoCompleteOnUpload).Title("Auto Complete").ClientTemplate("<input type='checkbox' #= autoCompleteOnUpload ? checked='checked' :'' # disabled />").Hidden(true);      
            columns.Command(command => { command.Edit().Text("Upload"); }).Width(230);
        })
                .Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("ClientDocumentUpload").Window(w => w.Events(e => e.Close("onCloseClientDocumentUpload"))))
        .Sortable()
        .Scrollable()
        .ClientDetailTemplateId("gridCaseDocumentsDetails")
        .Pageable(pager => pager.Refresh(true))
        .Resizable(resize => resize.Columns(true))
        .HtmlAttributes(new { style = "height:500px;" })
        .Events(clientEvents => clientEvents.DataBound("onRowDataBoundgridCaseDocuments"))             
        .DataSource(dataSource => dataSource
            .Ajax()
            .PageSize(20)
            .Events(events => events.Error("error_handlerCaseDocuments"))
            .Model(model => model.Id(p => p.ASSIGNMENT_DOCUMENT_TYPE_ID))
            .Read(read => read.Action("CaseDocuments_Read", "Home", new { id = Model.Item1.ASSIGNMENT_ID }))
            .Update(update => update.Action("CaseDocuments_Update", "Home"))           
            )
                       
    )
</div>
 
<script id="gridCaseDocumentsDetails" type="text/kendo-tmpl">
    @(Html.Kendo().Grid<ClientDocumentsExt>()
            .Name("gridCaseDocuments_#=ASSIGNMENT_DOCUMENT_TYPE_ID#")
            .Columns(columns =>
            {
                columns.Bound(m=>m.ASSIGNMENT_DOCUMENT_ID).Hidden(true);
                columns.Bound(m => m.FILE_NAME).Title("File Name");
                columns.Bound(m => m.uploadedBy).Title("Uploaded By").Width(210);
                columns.Bound(m => m.DATE_CREATED).Title("Upload Date").Format("{0:dd/MM/yyyy}").Width(110);
                columns.Command(c => c.Custom("Download").Click("onClickDownloadClientDoc")).Width(110);
            })
            .DataSource(dataSource => dataSource
                .Ajax()
                .PageSize(5)
                .Model(model => model.Id(m => m.ASSIGNMENT_DOCUMENT_ID))
                .Read(read => read.Action("gridCaseDocumentsDetails_Read", "Home", new { id = "#=ASSIGNMENT_DOCUMENT_TYPE_ID#" }))
 
            )
            .Pageable(pager => pager.Refresh(true))
            .Sortable()
            .Scrollable()
            .ToClientTemplate()
    )
</script>
 
<script type="text/javascript">
    function error_handlerCaseDocuments(e) {
        if (e.errors) {
            var message = "Errors:\n";
            $.each(e.errors, function (key, value) {
                if ('errors' in value) {
                    $.each(value.errors, function () {
                        message += this + "\n";
                    });
                }
            });
            alert(message);
        }
    }
 
    $("#gridCaseDocuments").find(".k-grid-content").height(421);
    function onClickDownloadClientDoc(e)
    {
        alert(e.ASSIGNMENT_DOCUMENT_ID);
    }
 
    function onRowDataBoundgridCaseDocuments(e) {
 
        var grid = $("#gridCaseDocuments").data("kendoGrid");
        var gridData = grid.dataSource.view();
        
        for (var i = 0; i < gridData.length; i++) {
            var currentUid = gridData[i].uid;
            if (gridData[i].COMPLETE_FLAG) {
                var currenRow = grid.table.find("tr[data-uid='" + currentUid + "']");
                $(currenRow).css("background-color", "rgb(164,198,57)");
            } else if (gridData[i].numOfUploadedFiles > 0)
            {
                var currenRow = grid.table.find("tr[data-uid='" + currentUid + "']");
                $(currenRow).css("background-color", "rgb(255,191,0)");
            }
        }
    }
    function onCloseClientDocumentUpload()
    {
        alert("onCloseClientDocumentUpload");
    }
</script>

Derek
Top achievements
Rank 1
 answered on 22 May 2015
3 answers
114 views

Hello,

 

What I am trying to achieve is add a placeholder in a dropdownlist that will display the binded model's property. When trying to use DisplayTextFor in the OptionLabel, I get "undefined" first option in the DropDownList. Is there a way to achieve this? I don't want to hardcode the OptionLabel.

 

Thanks

Georgi Krustev
Telerik team
 answered on 22 May 2015
1 answer
57 views

When I build a server bound grid with a pager and you click to go to the next page, it returns you to the top of the page (full page refresh). With an ajax grid, it keeps you at the same location on the page that you were on originally. This is not unexpected behavior, but is there a way to get around it?

Thanks!

Laurie

Laurie
Top achievements
Rank 2
 answered on 21 May 2015
7 answers
863 views
Hello,

My goal is to put a form inside a tabstrip content window. When I use the code below:
@(Html.Kendo().TabStrip()
.Name("tabstrip1")
.Items(tabstrip =>
{
tabstrip.Add().Text("Customer Information")
   .Content(@<div>
          @using (Ajax.BeginForm("AddData", "Customer", new AjaxOptions { HttpMethod = "post" }))
          {
          <input type="button" class="k-button" value="Submit" onclick="checkValues()" />
          }
          </div>
  );
 })
)

What happens is that the form generated by the html helper is not inside the tabstrip's div. Only the Submit button is.

But with the code below:
@(Html.Kendo().TabStrip()
.Name("tabstrip2")
.Items(tabstrip =>
{
    tabstrip.Add().Text("Customer Information")
         .Content(@<div>
                <form action="/Customer/AddData" data-ajax="true" data-ajax-method="post" id="form0" method="post" novalidate="novalidate">
                    <input type="button" class="k-button" value="Submit" onclick="checkValues()" />
                </form>
                </div>
                );
          })
    )

I get my desired effect. The form is inside the tabstrip's div along with the button.

I am just wondering if I'm not really gonna be able to use the html helper to create forms inside the tabstrip's content, or I am just missing something for the html helper to work. Your replies are much appreciated. 
Dimo
Telerik team
 answered on 21 May 2015
5 answers
646 views
I am using a solution from another post to create a click event in order to reload a tab each time you click on it.  I am having one issue though.  Each tab in my tabstrip uses LoadContentFrom to load a partial view.  Each of my partial views are Ajax forms (except for one).  When I add the click even script to the tabstrip, the first time I click on a tab it seems like it is loading it and then it never does.  If I click it a second time then it is fine.  Each time after that it is fine, it is just the first time.  The tab that doesn't have a form on it though does load the first time with no problems.  I am guessing it has something to do with the Ajax form which is calling the Get method on the controller and then the click event performing the same action?

If there is something I am not understanding or simply missing I would appreciate the help.

Here is my view with the tabstrip:

@model PASS.ViewModels.Proposals.UpdateViewModel
 
@{
    ViewBag.Title = "My Proposal";
}
 
<h2>My Proposal</h2>
 
@(Html.Kendo().TabStrip()
    .Name("tsProposal")
    .SelectedIndex(0)
    .Items(items =>
    {
        items.Add().Text("General").LoadContentFrom("_General", "Proposals", new { proposalID = Model.ID });
        items.Add().Text("Required Information").LoadContentFrom("_Required", "Proposals", new { proposalID = Model.ID });
        items.Add().Text("Associates").LoadContentFrom("_Experimenters", "Proposals", new { proposalID = Model.ID });
        items.Add().Text("Research").LoadContentFrom("_Questions", "Proposals", new { proposalID = Model.ID });
        items.Add().Text("Attachments").LoadContentFrom("_Attachments", "Proposals", new { proposalID = Model.ID });
        items.Add().Text("Time Request").LoadContentFrom("_TimeRequests", "Proposals", new { proposalID = Model.ID });
        items.Add().Text("Errors").LoadContentFrom("_Errors", "Proposals", new { proposalID = Model.ID });
    })
)
 
<script type="text/javascript">
$(document).ready(function () {
    var errorCount = @Html.Raw(Json.Encode(Model.Error_Count));
    var tabStrip = $("#tsProposal").data("kendoTabStrip");
 
    if (errorCount == 0) {
        $(tabStrip.items()[6]).attr("style", "display:none");
    }
 
    tabStrip.tabGroup.on('click', 'li', function (e) {
        tabStrip.reload($(this));
    });
})
</script>

And here is one of the partial views that loads into a tab and does not load upoin the first click:
@model PASS.ViewModels.Proposals.GeneralViewModel
 
@using (Ajax.BeginForm("_General", "Proposals", new AjaxOptions { UpdateTargetId = "generalReturnMsg", HttpMethod = "Post" }))
{
 
@Html.HiddenFor(model => model.Proposal_ID, Model.Proposal_ID)
     
<div class="editor-container">
    <div class="editor-label">
        @Html.Label("Title:")
    </div>
    <div class="editor-field">
        @Html.TextBoxFor(model => model.Title, new { style = "width: 350px;" })
        @Html.ValidationMessageFor(model => model.Title)
    </div>
    <br class="clear" />
    <br />
    <div class="editor-label">
        @Html.Label("Total hours requested for LIFE of the proposal")
    </div>
    <div class="editor-field">
        @Html.TextBoxFor(model => model.Total_Hours_Requested)
        @Html.ValidationMessageFor(model => model.Total_Hours_Requested)
    </div>   
    <br class="clear" />
    <br />
    <br />
    <p><input type="submit" value="Save" /></p>
     
    <div id="generalReturnMsg"></div>
 
</div>
     
}

Please let me know if you also need to see the controller code for the Get methods.

Thanks,

Steve









Daniel
Telerik team
 answered on 20 May 2015
1 answer
242 views

I can't seem to find any examples of adding a menu item to a splitbutton in a toolbar.  

Here is the code I have for the splitbutton:

        $("#toolbar").kendoToolBar({
            items: [
                {
                    type: "splitButton",
                    text: "Select",
                    id: "selectButton",
                    click: selectButtonClickHandler,
                    menuButtons: [
                        { text: "foo1" },
                        { text: "foo2" }
                    ]
                }

             ]
        });

I'm trying to do something like $("#selectButton").add(new menuButton("foo3"));

Is there a way to do this?  How have I missed it in the documentation?

Iliana Dyankova
Telerik team
 answered on 20 May 2015
5 answers
580 views

I'm trying to filter calendar MeetingAttendees which can have multiple users. I've built a filter and tested with various options, but it doesn't work. The basic example shows how to filter a calendar owner (which is a single value) and it works fine for me. But Attendees is an array and when I'm trying to filter that all my events disappear.

Here is my filter: 

    <script type="text/javascript">
        $(function () {
            $("#teamMembers :checkbox").change(function (e) {
 
 
                var checked = $.map($("#teamMembers :checked"), function (checkbox) {
                    return parseInt($(checkbox).val());
                });
                //alert(checked);
                var filter = {
                    logic: "or",
                    filters: $.map(checked, function (value) {
                        return {
                            operator: "eq",
                            field: "Attendees",
                            value: value
                        };
                    })
                };
                var scheduler = $("#scheduler").data("kendoScheduler");
                scheduler.dataSource.filter(filter);
 
 
            });
        })
    </script>
}

 

 

Here is the code that loads calendar events:

public virtual IQueryable<MeetingViewModel> GetAll()
{
    return db.Meetings.ToList().Select(meeting => new MeetingViewModel
    {
        MeetingID = meeting.MeetingID,
        Title = meeting.Title,
        Start = DateTime.SpecifyKind(meeting.Start, DateTimeKind.Utc),
        End = DateTime.SpecifyKind(meeting.End, DateTimeKind.Utc),
        StartTimezone = meeting.StartTimezone,
        EndTimezone = meeting.EndTimezone,
        Description = meeting.Description,
        IsAllDay = meeting.IsAllDay,
        SupportGroupId = meeting.SupportGroupId,
        RecurrenceRule = meeting.RecurrenceRule,
        RecurrenceException = meeting.RecurrenceException,
        RecurrenceID = meeting.RecurrenceID,
        Attendees = meeting.MeetingAttendees.Select(m => m.AttendeeID).ToArray(),
        ActivityTypeId = meeting.ActivityTypeId
    }).AsQueryable();
}

 

 

 

Here is my custom editor template:

@model Itsws.Models.MeetingViewModel
@{
    //required in order to render validation attributes
    ViewContext.FormContext = new FormContext();
}
 
@functions{
    public Dictionary<string, object> generateDatePickerAttributes(
           string elementId,
           string fieldName,
           string dataBindAttribute,
           Dictionary<string, object> additionalAttributes = null)
    {
 
        Dictionary<string, object> datePickerAttributes = additionalAttributes != null ? new Dictionary<string, object>(additionalAttributes) : new Dictionary<string, object>();
 
        datePickerAttributes["id"] = elementId;
        datePickerAttributes["name"] = fieldName;
        datePickerAttributes["data-bind"] = dataBindAttribute;
        datePickerAttributes["required"] = "required";
        datePickerAttributes["style"] = "z-index: inherit;";
 
        return datePickerAttributes;
    }
}
<div class="k-edit-label">
    @(Html.LabelFor(model => model.Title))
</div>
<div data-container-for="title" class="k-edit-field">
    @(Html.TextBoxFor(model => model.Title, new { @class = "k-textbox", data_bind = "value:title" }))
</div>
 
<div class="k-edit-label">
    @(Html.LabelFor(model => model.Start))
</div>
<div data-container-for="start" class="k-edit-field">
 
    @(Html.Kendo().DateTimePickerFor(model => model.Start)
        .HtmlAttributes(generateDatePickerAttributes("startDateTime", "start", "value:start,invisible:isAllDay")))
 
    @(Html.Kendo().DatePickerFor(model => model.Start)
        .HtmlAttributes(generateDatePickerAttributes("startDate", "start", "value:start,visible:isAllDay")))
 
    <span data-bind="text: startTimezone"></span>
    <span data-for="start" class="k-invalid-msg"></span>
</div>
 
<div class="k-edit-label">
    @(Html.LabelFor(model => model.End))
</div>
<div data-container-for="end" class="k-edit-field">
 
    @(Html.Kendo().DateTimePickerFor(model => model.End)
        .HtmlAttributes(generateDatePickerAttributes(
            "endDateTime",
            "end",
            "value:end,invisible:isAllDay",
            new Dictionary<string, object>() { { "data-dateCompare-msg", "End date should be greater than or equal to the start date" } })))
 
    @(Html.Kendo().DatePickerFor(model => model.End)
        .HtmlAttributes(generateDatePickerAttributes(
            "endDate",
            "end",
            "value:end,visible:isAllDay",
            new Dictionary<string, object>() { { "data-dateCompare-msg", "End date should be greater than or equal to the start date" } })))
 
    <span data-bind="text: endTimezone"></span>
    <span data-for="end" class="k-invalid-msg"></span>
</div>
 
<div class="k-edit-label">
    @(Html.LabelFor(model => model.IsAllDay))
</div>
<div data-container-for="isAllDay" class="k-edit-field">
    <input data-bind="checked: isAllDay" data-val="true" id="IsAllDay" name="IsAllDay" type="checkbox" />
</div>
 
@*<div class="endTimezoneRow">
        <div class="k-edit-label"></div>
        <div class="k-edit-field">
            <label class="k-check">
                <input checked="checked" class="k-timezone-toggle" type="checkbox" value="true" />
                Use separate start and end time zones
            </label>
        </div>
    </div>*@
<script>
    $(".k-timezone-toggle").on("click", function () {
        var isVisible = $(this).is(":checked");
        var container = $(this).closest(".k-popup-edit-form");
 
        var endTimezoneRow = container.find("label[for='EndTimezone']").parent().add(container.find("div[data-container-for='endTimezone']"));
        endTimezoneRow.toggle(isVisible);
 
        if (!isVisible) {
            var uid = container.attr("data-uid");
            var scheduler = $("\#scheduler").data("kendoScheduler");
            var model = scheduler.dataSource.getByUid(uid);
            model.set("endTimezone", null);
        }
    });
 
    var endTimezone = '${data.endTimezone}';
 
    if (!endTimezone || endTimezone == "null") {
        $(".k-timezone-toggle").trigger('click');
    }
</script>
 
@*<div class="k-edit-label">
        @(Html.LabelFor(model => model.StartTimezone))
    </div>
    <div data-container-for="startTimezone" class="k-edit-field">
        @(Html.Kendo().TimezoneEditorFor(model => model.StartTimezone)
            .HtmlAttributes(new { data_bind = "value:startTimezone" }))
    </div>
 
    <div class="k-edit-label">
        @(Html.LabelFor(model => model.EndTimezone))
    </div>
    <div data-container-for="endTimezone" class="k-edit-field">
        @(Html.Kendo().TimezoneEditorFor(model => model.EndTimezone)
            .HtmlAttributes(new { data_bind = "value:endTimezone" }))
    </div>*@
 
<div class="k-edit-label">
    @(Html.LabelFor(model => model.RecurrenceRule))
</div>
<div data-container-for="recurrenceRule" class="k-edit-field">
    @(Html.Kendo().RecurrenceEditorFor(model => model.RecurrenceRule)
        .HtmlAttributes(new { data_bind = "value:recurrenceRule" }))
</div>
 
<div class="k-edit-label">
    @(Html.LabelFor(model => model.Description))
</div>
 
<div data-container-for="description" class="k-edit-field">
    @(Html.TextAreaFor(model => model.Description, new { @class = "k-textbox", data_bind = "value:description" }))
</div>
 
<div class="k-edit-label">
    @(Html.LabelFor(model => model.ActivityTypeId))
</div>
<div data-container-for="ActivityTypeId" class="k-edit-field">
    @(Html.Kendo().DropDownListFor(model => model.ActivityTypeId)
        .HtmlAttributes(new { data_bind = "value:ActivityTypeId", style = "width: 280px" })
        .DataTextField("Text")
        .DataValueField("Value")
        .OptionLabel("None")
        .ValuePrimitive(true)
        .Template("<span class='k-scheduler-mark' style='background-color:\\#= data.Color?Color:'' \\#'></span>\\#=Text\\#")
        .BindTo(ViewBag.ActivityTypes).ToClientTemplate()
    )
</div>
 
<div class="k-edit-label">
    @(Html.LabelFor(model => model.SupportGroupId))
</div>
<div data-container-for="ActivityTypeId" class="k-edit-field">
    @(Html.Kendo().DropDownListFor(model => model.SupportGroupId)
        .HtmlAttributes(new { data_bind = "value:SupportGroupId", style = "width: 280px" })
        .DataTextField("Text")
        .DataValueField("Value")
        .OptionLabel("None")
        .ValuePrimitive(true)
        .Template("<span class='k-scheduler-mark' style='background-color:\\#= data.Color?Color:'' \\#'></span>\\#=Text\\#")
        .BindTo(ViewBag.SupportGroups).ToClientTemplate()
    )
</div>
 
<div class="k-edit-label">
    @(Html.LabelFor(model => model.Attendees))
</div>
<div data-container-for="Attendees" class="k-edit-field">
    @(Html.Kendo().MultiSelectFor(model => model.Attendees)
        .HtmlAttributes(new { data_bind = "value:Attendees" })
        .DataTextField("Text")
        .DataValueField("Value")
        .ValuePrimitive(true)
        .TagTemplate("<span class='k-scheduler-mark' style='background-color:\\#= data.Color?Color:'' \\#'></span>\\#=Text\\#")
        .ItemTemplate("<span class='k-scheduler-mark' style='background-color:\\#= data.Color?Color:'' \\#'></span>\\#=Text\\#")
        .BindTo(ViewBag.TeamMembers).ToClientTemplate()
    )
</div>
 
@{
    ViewContext.FormContext = null;
}

 

 

 

Here is the sheduler code:

@(Html.Kendo().Scheduler<Itsws.Models.MeetingViewModel>()
        .Name("scheduler")
        .Date(DateTime.Today)
        .Editable(editable =>
        {
            editable.TemplateName("CustomEditorTemplate");
        })
        .StartTime(new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 7, 00, 00))
        .Height(600)
        .Views(views =>
        {
            views.DayView();
            views.WeekView(weekView => weekView.Selected(true));
            views.MonthView();
            views.AgendaView();
            views.TimelineView();
        })
        .Timezone("Etc/UTC")
        .DataSource(d => d
                .Model(m =>
                {
                    m.Id(f => f.MeetingID);
                    m.Field(f => f.Title).DefaultValue("No title");
                    m.RecurrenceId(f => f.RecurrenceID);
                    m.Field(f => f.Title).DefaultValue("No title");
                })
            .Read("Meetings_Read", "Scheduler")
            .Create("Meetings_Create", "Scheduler")
            .Destroy("Meetings_Destroy", "Scheduler")
            .Update("Meetings_Update", "Scheduler")
        )
)

HDC
Top achievements
Rank 1
 answered on 20 May 2015
1 answer
103 views

Hello everyone,

 

I'm currently testing the Kendo Ui, especially the Grid, in an ASP.NET MVC - Environment and I'm a bit confused by the AJAX-Databinding.

The grid is constructed with the Kendo MVC GridBuilder in a razor-view.

There are multiple columns that are set to visible / invisible dynamically.

Everything was working like a charm until I've inspected the network-traffic that showed me, that the JSON-Result contains every column of the IEnumerable the grid is bound to, also the ones that are not even mentioned in the Columns-section.

Is there a way to turn this off and only download the data that is actually needed?

 

Thanks.

 

Kind regards,

 

Stefan

 

Dimiter Madjarov
Telerik team
 answered on 20 May 2015
3 answers
543 views

Hi,

I am trying to load the razor page/ form as acontent for TabStrip dynamically from Menu click event. The telerik team can help to with sample example.

 

Thanks,

Kiran

Daniel
Telerik team
 answered on 20 May 2015
Narrow your results
Selected tags
Tags
+? more
Top users last month
Anislav
Top achievements
Rank 6
Silver
Bronze
Bronze
Jianxian
Top achievements
Rank 1
Iron
Marco
Top achievements
Rank 3
Iron
Iron
Iron
Jim
Top achievements
Rank 2
Iron
Iron
Nurik
Top achievements
Rank 2
Iron
Iron
Want to show your ninja superpower to fellow developers?
Top users last month
Anislav
Top achievements
Rank 6
Silver
Bronze
Bronze
Jianxian
Top achievements
Rank 1
Iron
Marco
Top achievements
Rank 3
Iron
Iron
Iron
Jim
Top achievements
Rank 2
Iron
Iron
Nurik
Top achievements
Rank 2
Iron
Iron
Want to show your ninja superpower to fellow developers?
Want to show your ninja superpower to fellow developers?