Nueva publicación

Encontrar

Pregunta
· 8 jul, 2024

Error: Invalid Community Edition license, may have exceeded core limit. - Shutting down the system : $zu(56,2)= 0 (Probléme avec : irishealth-community:2024.1 )

 Bonjour,

Depuis ce matin j'arrive pas à compiler ou lancer mes programmes qui tourne en local sur docker avec l'image : intersystemsdc/irishealth-community:2024.1-zpm

J'ai toujours cette erreur sur le terminal ou le portal de management : request to http://localhost:52773/api/atelier/ failed, reason: socket hang up

Dans mes logs docker aussi j'ai des erreurs en conitnu , voici un extrait ...

 

Dans le fichier message.log j'ai aussi des erreurs et voici un extrait 

 

L'erreur semble indiguer une licence et un nombre de core limite ....

Avec l'ajout de ceci dans mon docker-compose.yml  comme l'indique cette doc :https://docs.intersystems.com/irisforhealth20232/csp/docbook/Doc.View.cl...

    deploy:
      resources:
        limits:
          cpus: '8'
    cpuset: "0-7"

 

Le probléme persiste toujours.

Savez-vous comment faire pour résoudre ce probléme ?

Merci d'avance

5 comentarios
Comentarios (5)2
Inicie sesión o regístrese para continuar
Pregunta
· 8 jul, 2024

Error: Invalid Community Edition license, may have exceeded core limit. - Shutting down the system : $zu(56,2)= 0

Bonjour,

Depuis ce matin j'arrive pas à compiler ou lancer mes programmes qui tourne en local sur docker avec l'image : intersystemsdc/irishealth-community:2024.1-zpm

J'ai toujours cette erreur sur le terminal ou le portal de management : request to http://localhost:52773/api/atelier/ failed, reason: socket hang up

Dans mes logs docker aussi j'ai des erreurs en conitnu , voici un extrait ...

 

Dans le fichier message.log j'ai aussi des erreurs et voici un extrait 

 

L'erreur semble indiguer une licence et un nombre de core limite ....

Avec l'ajout de ceci dans mon docker-compose.yml  comme l'indique cette doc :https://docs.intersystems.com/irisforhealth20232/csp/docbook/Doc.View.cl...

    deploy:
      resources:
        limits:
          cpus: '8'
    cpuset: "0-7"

 

Le probléme persiste toujours.

Savez-vous comment faire pour résoudre ce probléme ?

Merci d'avance

1 Comentario
Comentarios (1)2
Inicie sesión o regístrese para continuar
Anuncio
· 8 jul, 2024

Concours InterSystems Python 2024

Salut la Communauté,

Nous sommes heureux de vous inviter au prochain concours de programmation en ligne InterSystems, axé sur Python !

🏆 Concours InterSystems Python 🏆

Durée : 15 juillet - 4 août 2024

Prix : $14,000$


Le sujet

Développez n'importe quelle solution à l'aide d'InterSystems IRIS, d'InterSystems IRIS for Health ou d'IRIS Cloud SQL qui utilise Python (ou Embedded Python) comme langage de programmation.

Exigences générales :

  1. Une application ou une bibliothèque doit être entièrement fonctionnelle. Il ne doit pas s'agir d'un import ou d'une interface directe pour une bibliothèque déjà existante dans un autre langage (sauf pour le C++, là il faut vraiment faire beaucoup de travail pour créer une interface pour Iris). Il ne doit pas s'agir d'un copier-coller d'une application ou d'une bibliothèque existante.
  2. Applications acceptées : nouvelles applications Open Exchange ou existantes, mais avec une amélioration significative. Notre équipe examinera toutes les candidatures avant de les approuver pour le concours.
  3. L'application doit fonctionner soit sur IRIS Community Edition, soit sur IRIS for Health Community Edition. Les deux peuvent être téléchargés en tant que versions hôtes (Mac, Windows) à partir du site d'évaluation, ou peuvent être utilisés sous la forme de conteneurs extraits d'InterSystems Container Registry ou de Community Containers : intersystemsdc/iris-community:latest ou intersystemsdc/irishealth-community:latest .
  4. L'application doit être Open Source et publiée sur GitHub.
  5. Le fichier README de l'application doit être en anglais, contenir les étapes d'installation et contenir soit la vidéo de démonstration ou/et une description du fonctionnement de l'application.
  6. Pas plus de 3 soumissions d’un développeur sont autorisées.

N.B. Nos experts auront le dernier mot quant à l'approbation ou non de la candidature au concours en fonction des critères de complexité et d'utilité. Leur décision est définitive et sans appel.

Prix ​​du concours :

1. Nomination des experts – les gagnants seront sélectionnés par l'équipe d'experts d'InterSystems :

🥇 1ère place - $5,000
🥈 2e place - $3,000
🥉 3e place - $1,500
🏅 4e place - $750
🏅 5e place - $500
🌟 6-10e places - $100

2. Gagnants de la communauté – candidatures qui recevront le plus de votes au total :

🥇 1ère place - $1,000 
🥈 2e place - $750
🥉 3e place - $500
🏅 4e place - $300
🏅 5e place - $200

Remarque : si plusieurs participants obtiennent le même nombre de votes, ils sont tous considérés comme gagnants et le prix est partagé entre les gagnants.

Qui peut participer ?

Tout membre de la communauté de développeurs, à l'exception des employés d'InterSystems (sous-traitants ISC autorisés). Créer un compte !

Les développeurs peuvent s'associer pour créer une application collaborative. Autorisé de 2 à 5 développeurs dans une équipe.

N'oubliez pas de mettre en évidence les membres de votre équipe dans le README de votre application – profils d'utilisateurs DC.

Délais importants :

🛠 Phase de développement et d'inscription de l'application :

  • 15 juillet 2024 (00:00 EST): le concours commence.
  • 28 juillet 2024 (23:59 EST): la date limite de soumission.

 Période de vote:

  • 29 juillet 2024 (00:00 EST): le vote commence.
  • 4 août 2024 (23:59 EST): le vote se termine.

Remarque : Les développeurs peuvent améliorer leurs applications tout au long de la période d'inscription et de vote.

    Ressources utiles :

    ✓ Documentation :

    ✓ Exemples d'applications et de bibliothèques :

    ✓ Cours en ligne :

    ✓ Vidéos :

    ✓ Pour les débutants avec IRIS :

    ✓ Pour les débutants avec ObjectScript Package Manager (IPM) :

    ✓ Comment soumettre votre application au concours :

    Besoin d'aide ?

    Rejoignez la chaîne du concours sur le serveur Discord d'InterSystems ou discutez avec nous dans les commentaires de ce post.

    Nous avons hâte de voir vos projets! Bonne chance 👍


    En participant à ce concours, vous acceptez les conditions du concours énoncées ici. Veuillez les lire attentivement avant de continuer.

    Comentarios (0)1
    Inicie sesión o regístrese para continuar
    Artículo
    · 8 jul, 2024 Lectura de 19 min

    Um portal para administrar armazenamento feito com Django - Parte 2

    Nosso objetivo

    Hoje vamos continuar expandindo o último artigo compartilhando informações sobre alguns recursos que adicionamos em nosso portal. Vamos incluir uma pitada de CSS para visualizar os dados disponíveis melhor e exportá-los. Finalmente, estudaremos como adicionar opções de filtros e ordenação. Ao fim deste artigo, você deve ser capaz de exibir esteticamente uma query simples completa.

    Anteriormente, em "Um portal para administrar armazenamento feito com Django"...

    Vamos voltar de onde paramos antes de seguir o desenvolvimento do portal. Anteriormente, criamos a a base do projeto em linha de comando com alguns códigos prontos do Django como startproject. Então, adicionamos os requisitos para conectar à base de dados no arquivo requirements.txt e seus parâmetros em settings.py para simplificar a instalação. Então, criamos uma aplicação Globals com as URLs apropriadas e alguns caminhos direcionando os usuários do projeto principal até as views, que por sua vez se comunicam com os dados por meio de modelos. Também criamos uma pasta API com alguns métodos de levantar informações sobre uma base de dados remota. Com tudo mencionado acima, deixamos uma opção para criar comunicação entre instâncias IRIS diferentes. Finalmente, fizemos o index.html para exibir tudo isso no link http://127.0.0.1:8000/globals/.

    Nessa altura, nossos bastidores devem parecer com a imagem abaixo.

    No entanto, não tão arrumado quanto a ilustração anterior, o nosso palco principal se parece como o print de tela que segue.

    Adicionando CSS

    A Cascading Style Sheets (CSS - folhas de estilo em cascata) pode transformar esse projeto em algo muito mais apresentável, de melhor aparência e mais agradável de se trabalhar. Nessa seção, você aprenderá como usar CSS no seu projeto. Também vamos te guiar por alguns conceitos básicos dessa linguagem. No entand=to, nosso objetivo principal será conectar o arquivo de estilos e o projeto.

    Em primeiro lugar, crie uma pasta chamada "static" dentro do diretório /globals. Precisaremos dela para guardar todos os nossos arquivos estáticos posteriormente. Dentro dessa pasta, você pode adicionar o arquivo styles.css.

    Agora nós finalmente podemos tornar tudo limpo e colorido. Contudo, se você não conhece nada sobre CSS, não se preocupe! Tenho boas notícias par você: é bastante intuitivo para começar. Tudo o que você precisa é escrever o elemento e adicionar o design entre chaves {}. Você pode acessar classes, sinalizando-as com um ponto, e IDs, sinalizando-os com uma hashtag #. Se quiser uma dica profissional, você pode usar um asterisco para adicionar o estilo a cada elemento dentro desse arquivo HTML.

    Por exemplo, se adicionarmos um ID e uma classe aos últimos três parágrafos do index.html, poderemos acessá-los separadamente e adicionar diferentes cores, fundos e fontes.

    <p>showing results for {{globals.count}} globals</p>
    <p class="totalSize">total size: {{sumSize.size__sum}}</p>
    <p id="allocatedSize">total allocated size: {{sumAllocated.allocatedsize__sum}}</p>
    * {
        font-family: 'Lucida Sans';
    }
    
    p {
        background-color: yellow;
    }
    
    .totalSize {
        color: brown;
    }
    
    #allocatedSize {
        font-weight: bold;
    }

    De acordo com esse código, depois de configurar as conexões apropriadas, toda fonte exibida na página deve ser da família Lucida Sans, os três parágrafos devem ter um fundo amarelo, o parágrafo com a classe totalSize deve ter uma fonte marrom e o parágrafo com o ID allocatedSize terá uma fonte em negrito.

    Você deve notar algumas peculiaridades se brincar um pouco com os elementos adicionando IDs, classes e estilos. O primeiro é hierarquia: as definições de IDs, sobrescrevem as de classes, que por sua vez sobrescrevem os estilos gerais. Segundo, você pode ter vários elementos compartilhando uma mesma classe. Além disso, itens filhos herdarão a maioria do estilo de seus itens pais (algumas coisas não serão herdadas, mas isso é um tópico mais avançada que não cobriremos nesse artigo). Se desejar, compartilhe conosco nos comentários qual desses comportamentos você notou e quais você ainda não sabia.

    Em seguida, precisamos fazer o projeto entender o que é uma folha de estilo e onde encontrá-la. Então, podemos colocar a referência ao styles.css no arquivo HTML.

    Primeiro, vá para settings.py, procure pela variável STATIC_URL e mude seu valor para o que segue.

    STATIC_URL = '/static/'

    Essa configuração deve notificar o projeto que todo arquivo estático pode ser encontrado numa pasta chamada "static", dentro da pasta do app. Nesse caso, é o diretório /globals/static. Se tivermos outro app sendo usado por esse projeto, ele só reconheceria sua própria pasta interna static (a não ser que seja especificado que haja uma geral).

    Arquivos estáticos são aqueles que não mudam quando a aplicação está rodando. Você pode usá-los para guardar funções, definições, constantes e imagens que dão assistência ao código (nesse caso, arquivos .py) durante sua execução. Na prática, é aqui que você guarda JavaScript e CSS.

    O próximo passo é referenciá-la do index.html. Adicione uma tag <head>> antes do corpo <body>. Dentro do <body>, use uma tag <link> para relacionar a uma folha de estilo do tipo text/CSS com a referência "{% static 'styles.css' %}" e media "screen". Além disso, você precisa dizer ao Django para carregar os estáticos. Lembre-se que podemos "dizer ao Django" coisas por meio do arquivo HTML adicionando código entre chaves e símbolos de porcentagem, como mostrado no exemplo: "{% seu código aqui %}".

    <head>
        {% load static %}
        <link rel="stylesheet" type="text/CSS" href="{% static 'styles.css' %}" media="screen"/>
    </head>

    Eu mudei nossa lista de globais para uma tabela com uma sintaxe similar. Então, adicionei ao projeto um bom espaçamento entre os elementos assim como as cores da Innovatium. Você pode checar o arquivo CSS que eu criei no meu GitHub e ver como essa tabela ganhou a aparência ilustrada abaixo. Não sou especialista em CSS ou web design. No entanto, se tiver questões eu ficarei feliz em ajudar e quem sabe até aprender novas coisas juntos. Deixe um comentário ou me mande uma mensagem!

    <table>
        <thead>
            <tr>
                <th>Database</th>
                <th>Global</th>
                <th>Size</th>
                <th>Allocated</th>
            </tr>
        </thead>
        <tbody>
            {% for global in globals %}
            <tr>
                <td>{{ global.database }}</td>
                <td>{{ global.name }}</td>
                <td>{{ global.size }}</td>
                <td>{{ global.allocatedsize }}</td>
            </tr>
            {% endfor %}
        </tbody>
    </table>


    PS.: se os arquivos estáticos estão em cache, você pode não ver mudanças ao recarregar. Você pode apertar Ctrl+Shift+Delete e remover o cache armazenado quando você usa o Google Chrome como navegador. Então, recarregue a página outra vez. Se tiver feito tudo corretamente, verá o seguinte no seu terminal:

     

    DICA: para evitar a necessidade de limpar o cache toda vez que usa o programa, adicione a linha a seguir à <head> do seu arquivo HTML: <meta http-equiv="cache-control" content="no-cache" />. Essa tag deve previnir a página de armazenar o cache.

    Exportando dados

    Nessa seção, vamos retornar ao backend. Pode ser uma boa ideia revisar a parte 1 dessa série de artigos caso você não esteja familiarizado com o caminho que as requisições seguem (template -> URL -> view -> base de dados e então de volta).

    Vamos fazer um formulário para que o usuário escolha exportar para CSV, XML ou JSON, já que essas linguagens já cobrem a maioria dos usos para transferência de dados. Ainda assim, você pode adicionar quantas linguagens quiser. Para cumprir nossa tarefa, precisaremos de um formulário com um método HTTP, um token de segurança, três inputs de radio (você vai ver em breve o que raios é isso) e um botão de enviar.

    <form method="GET">
        {% csrf_token %}
        <input type="radio" name="exportLanguage" value="CSV"/>
        <label for="CSV">CSV</label>
        <input type="radio" name="exportLanguage" value="XML"/>
        <label for="XML">XML</label>
        <input type="radio" name="exportLanguage" value="JSON"/>
        <label for="JSON">JSON</label>
        <button type="submit" formaction="{% url 'export' %}"> Export </button>
    </form>

    Se quiser que as tags <label> mostrem um texto "clicável" para o valor correspondente, adicione a propriedade "onclick" na tag com o valor getElementById(‘The corresponding ID’).checked = true, assim como IDs correspondentes para cada opção. A propriedade formaction especificada no botão, direciona à URL. Como resultado, você pode ter quantos botões quiser apontando para URLs diferentes, para enviar o formulário de acordo com a ação desejada.

    Quando finalizado o passo anterior, podemos adicionar o caminho que nos direciona à view em urls.py e finalmente criar a view em views.py. Essa view deve parecer um pouco mais complexa em comparação às que já fizemos anteriormente mas, passo a passo, vamos conseguir criá-la juntos.

    from .views import home, update, export
    
    urlpatterns = [
        path('', home),
        path('update', update, name="update"),
        path('export', export, name="export")
    ]

    Primeiro, precisamos atribuir uma variável para referenciar as globais. Então, precisamos criar um caminho onde o arquivo deve aparecer quando o usuário clica no botão de exportar (podemos fazê-lo editável no lado do cliente). Além disso, precisamos saber qual linguagem foi selecionada e fazer a exportação apropriada para cada uma.

    import os
    
    def export(request):
        globals = irisGlobal.objects.all()           # pega as globais
        cd = os.getcwd()                             # pega o diretório atual
        language = request.GET.get("exportLanguage") # pega a linguagem selecionada no formulário
        if language == "CSV":
            pass
        elif language == "XML":
            pass
        elif language == "JSON":
            pass
        return redirect(home)

    Para o CSV, tudo o que precisamos fazer é colocar cada registro numa linha e cada coluna separada por uma vírgula. A maneira mais intuitiva é concatenar toda a informação de cada global numa string entre vírgulas, seguida por um terminador de linha e escrever cada uma em um arquivo.

    if language == "CSV":
        with open(cd+"\\test.csv", "w") as file:
            for eachGlobal in globals:
                row = eachGlobal.database+", "+eachGlobal.name+", "+str(eachGlobal.size)+", "+str(eachGlobal.allocatedsize)+"\n"
                file.write(row)
            

    Para o JSON e XML, vamos precisar dos serializadores Django. Eles podem parecer complexos mas, na realidade, são bem simples. O módulo de serializadores tem dois métodos: serialize deserialize, que podem converter informação de e para a sua linguagem de preferência. Você também pode projetar serializadores customizados. Por sorte, os de XML e JSON já existem.

    from django.core import serializers
    
    [...]
    
    elif language =="XML":
        with open(cd+"\\test.xml", "w") as file:
            globals = serializers.serialize("xml", globals)
            file.write(globals)
            
    elif language =="JSON":
        with open(cd+"\\test.json", "w") as file:
            globals = serializers.serialize("json", globals)
            file.write(globals)

    Muito bem! A aplicação está finalmente pronta para recarregar e testar. Depois de exportar sua área de trabalho deve magicamente se parecer como a imagem abaixo:
     

    Filtros

    Vamos começar filtrando por base de dados. Precisamos fazer uma tag de formulário com input de texto para colocar o nome da base de dados e referência à URL. Podemos usar a view home com algumas adaptações.

    <form method="GET" action="{% url 'home' %}">
        {% csrf_token %}
        <input type="text" name="database" placeholder="Database"/>
    </form>

    Já que agora estamos referenciando o caminho home no index, vamos dar um nome a ele nas patterns, em urls.py.

    path('', home, name="home"),

    Lembre-se que na view home, pegamos todas as globais do modelo com irisGlobal.objects.all() e as retornamos ao index. Nesse ponto, precisamos retornar apenas um conjunto filtrado delas, ao invés de todas. A boa notícia é que vamos resolver esse problema com apenas quatro linhas de código.

    Primeiro, assim como fizemos na exportação, precisamos buscar informação do input com request.GET.get() e reduzir nosso conjunto de globais de acordo com o que o usuário deseja. Graças à ajuda do objeto de consulta do Django.db.models, seremos capazes de usar a função de filtro para atingir nosso objetivo.

    from django.db.models import Sum, Q
    from .models import irisGlobal
    
    def home(request):
        globals = irisGlobal.objects.all()
        databaseFilter = request.GET.get("database")
        
        if databaseFilter:
            query = Q(database__contains=databaseFilter)
            globals = globals.filter(query)
            

    O Q() é o objeto de consulta (Query). Dentro desse objeto, você pode adicionar o nome de uma coluna, dois underlines e uma declaração SQL para refinar a busca. Depois disso, você pode passar o quaisquer objetos Q que você quiser como argumentos da função filter (filtro), e serão unidos por operadores "AND" (a não ser que você especifique para juntar com "OR"). Tem muitas outras coisas que você pode fazer com a classe Q. Se quiser, pode ler tudo sobre ele e outras maneiras de fazer consultas no Django na documentação oficial.

    Agora você pode recarregar e testar seus filtros. Lembre-se de prestar atenção em como os agregadores no fim da página se adaptam aos filtros, já que os construímos a partir da variável globals.

    Mais filtros!

    Se você se sentiu confortável com a última seção, podemos ficar mais confiantes com o assunto. É hora de adicionar mais filtros e combiná-los. Para começar, vamos colocar alguns outros inputs no nosso formulário.

    <form method="GET">
        {% csrf_token %}
        <input type="text" name="database" placeholder="Database"/>
        <input type="text" name="global" placeholder="Global name"/>
        <input type="number" name="size" placeholder="Size" step="0.001"/>
        <input type="number" name="allocated" placeholder="Allocated size" step="0.001"/>
        <button type="submit" formaction="{% url 'home' %}"> Filter </button>
    </form>

    Na view, adicione os novos filtros à variável globals. Eles devem formar uma cadeia e serão equivalentes à declaração SQL abaixo.

    SELECT * FROM globals

    WHERE database LIKE ‘%databaseFilter%’ AND

          globals LIKE ‘%globalsFilter%’ AND

          size >=sizeFilter AND

          allocatedsize>=allocFilter

    globals = irisGlobal.objects.all()
    databaseFilter = request.GET.get("database")
    globalFilter = request.GET.get("global")
    sizeFilter = request.GET.get("size")
    allocFilter = request.GET.get("allocated")
    
    if databaseFilter:
        globals = globals.filter(Q(database__contains=databaseFilter))
    else:
        databaseFilter=""
    if globalFilter:
        globals = globals.filter(Q(name__contains=globalFilter))
    else:
        globalFilter=""
    if sizeFilter:
        globals = globals.filter(Q(size__gte=sizeFilter))
    else:
        sizeFilter=""
    if allocFilter:
        globals = globals.filter(Q(allocatedsize__gte=allocFilter))
    else:
        allocFilter=""

    O filtro já está funcionando, mas ainda podemos melhorar um pouco. Se passarmos as variáveis recebidas no return, poderemos usá-las como valores nos inputs. Então, elas não irão desaparecer quando recarregarmos a página ou apertarmos o botão filter.

    return render(request, "index.html", {"globals": globals,
        "sumSize": sumSize,
        "sumAllocated":sumAllocated,
        "database":databaseFilter
        "global":globalFilter
        "size":sizeFilter,
        "allocated":allocFilter
    })
    <form method="GET">
        {% csrf_token %}
        <input type="text" name="{{database}}" placeholder="Database"/>
        <input type="text" name="{{global}}" placeholder="Global name"/>
        <input type="number" name="{{size}}" placeholder="Size" step="0.001"/>
        <input type="number" name="{{allocated}}" placeholder="Allocated size" step="0.001"/>
        <button type="submit" formaction="{% url 'home' %}"> Filter </button>
    </form>

    Podemos fornecer aos filtros opções para atualizações que são menores ou iguais que um valor específico. Também podemos programar atualizações ao vivo (atualização a cada tecla que o usuário aperta enquanto digita os inputs). No entanto, por hora vamos deixar isso em mente como apenas ideias e vamos seguir para adicionar ordenação.

    Exportando um conjunto filtrado

    Depois de tudo o que fizemos, é natural que você queira adaptar a view de exportação para funcionar com os filtros que adicionamos.

    Podemos colocar toda a lógica que adicionamos aos filtros em uma função, que chamaremos de handle_filters, e ao invés de usar a array criada no irisGlobals.objects.all() para obter a informação, vamos usar a criada por essa função. Para fazer tudo isso funcionar, vamos colocar os dois formulários juntos.

    def handle_filters(request):
        globals = irisGlobal.objects.all()
        databaseFilter = request.GET.get("database")
        globalFilter = request.GET.get("global")
        sizeFilter = request.GET.get("size")
        allocFilter = request.GET.get("allocated")
        
        if databaseFilter:
            globals = globals.filter(Q(database__contains=databaseFilter))
        else:
            databaseFilter=""
        if globalFilter:
            globals = globals.filter(Q(name__contains=globalFilter))
        else:
            globalFilter=""
        if sizeFilter:
            globals = globals.filter(Q(size__gte=sizeFilter))
        else:
            sizeFilter=""
        if allocFilter:
            globals = globals.filter(Q(allocatedsize__gte=allocFilter))
        else:
            allocFilter=""
        return globals, databaseFilter, globalFilter, sizeFilter, allocFilter
    def export(request):
        globals = handle_filters(request)[0]
    <form method="GET">
        {% csrf_token %}
        <input type="radio" name="exportLanguage" value="CSV"/>
        <label for="CSV">CSV</label>
        <input type="radio" name="exportLanguage" value="XML"/>
        <label for="XML">XML</label>
        <input type="radio" name="exportLanguage" value="JSON"/>
        <label for="JSON">JSON</label>
        <button type="submit" formaction="{% url 'export' %}"> Export </button>
        <br/>
        <input type="text" name="{{database}}" placeholder="Database"/>
        <input type="text" name="{{global}}" placeholder="Global name"/>
        <input type="number" name="{{size}}" placeholder="Size" step="0.001"/>
        <input type="number" name="{{allocated}}" placeholder="Allocated size" step="0.001"/>
        <button type="submit" formaction="{% url 'home' %}"> Filter </button>
    </form>

     

    Ordenar tabela (com JavaScript)

    Essa seção irá te mostrar como eu adicionei opções de ordenação à tabela. Há muitas maneiras de fazer isso, mas hoje vamos usar JavaScript para aprender algo diferente do que já fizemos antes. É claro que será melhor se você já tiver algum conhecimento dos conceitos básicos da linguagem, mas você será capaz de acompanhar de qualquer maneira. Entretanto, o foco principal aqui é entender as conexões. Elas serão bastante similares às do CSS e abrirão ainda mais portas para você administrar dados no portal.

    Vamos começar! Abra o index.html e adicione duas tags <script> lá no final do <body>. A primeira deve fazer referência às dependências. A segunda aponta para o arquivo .js no nosso projeto (vamos criá-lo no passo seguinte). Já que já adicionamos o "{% load static %}", isso será suficiente para o arquivo JavaScript começar a funcionar.

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="{% static 'index.js'%}"></script>

    Uma vez que essa conexão for estabelecida, crie um arquivo dentro da pasta /static e nomeie como index.js (ou qualquer que seja o nome que você chamou na referência). Se, nesse ponto, você adicionar um  console.log(“Hello world!”); ao arquivo e recarregar a página, poderá ver que já está funcionando. Isso significa que podemos finalmente começar a criar a lógica de ordenação.

    Queremos que a tabela seja ordenada quando o usuário clica em alguma header. Para tornar isso possível, diremos ao dispositivo de exibição para escutar ao usuário quando ele clica em qualquer uma das headers. Temos o documento, do qual selecionamos cada elemento <th> da tabela e, para cada um deles, queremos saber quando foi clicado.

    document.querySelectorAll("table th").forEach(header => {
        header.addEventListener("click", () => {
            
        });
    })

    Agora podemos dizer o que fazer quando ouve o evento "click". Precisaremos da tabela (item pai de <thead>, que é o item pai de <tr>, que por sua vez é o item pai do <th> clicado) e um número indicando qual header foi selecionada. Também precisamos saber se a tabela já está em ordem crescente por essa coluna. Então, chamamos uma função para ordenar a tabela.

    document.querySelectorAll("table th").forEach(header => {
        header.addEventListener("click", () => {
            const table = header.parentElement.parentElement.parentElement;
            const columnIndex = Array.prototype.indexOf.call(header.parentElement.children, header);
            const isAscending = header.classList.contains("ascending");
            sortTable(table, columnIndex+1, !isAscending);
        });
    })

    Existem muitos algoritmos de ordenação de tabela já criados. Você pode até fazer o download de algum e usá-lo. Eu quero evitar adicionar mais dependências a esse projeto, então vou usar o algoritmo a seguir.

    function sortTable(table, columnIndex, ascending = true) {
        const direction = ascending ? 1 : -1;                 // se for crescente, a direção é 1, se não, é -1
        const header = $('th:nth-child('+columnIndex+')');    // pega a header com índice da coluna
        const body = table.children[1]                        // pega o body (segundo item filho da tabela)
        const rows = Array.from(body.querySelectorAll("tr")); // cria um array para as linhas no body
        // remove ordenação anterior de todas as headers
        table.querySelectorAll("th").forEach(th => th.classList.remove("ascending", "descending"));
    
        // adiciona ordenação à header selecionada
        header[0].classList.toggle("ascending", ascending);
        header[0].classList.toggle("descending", !ascending);
    
        // algoritmo de ordenação das linhas
        const sorted = rows.sort((a, b) => {
            const aColumn = a.querySelector('td:nth-child('+columnIndex+')').textContent;
            const bColumn = b.querySelector('td:nth-child('+columnIndex+')').textContent;
    
            return aColumn > bColumn ? (1*direction) : (-1*direction);
        });
    
        // remove as linhas do body e adiciona as linhas ordenadas
        while (body.firstChild) {
            body.removeChild(body.firstChild);
        }
        body.append(...sorted);
        
    }

    O link a seguir explica o algoritmo mostrado acima. https://dcode.domenade.com/tutorials/how-to-easily-sort-html-tables-with-css-and-javascript

    Agora, com algum CSS, você tem uma tabela bonita e ordenada.

    .ascending::after {
        content: "\25be";
    }
    
    .descending::after {
        content: "\25b4";
    }
    
    .ascending, .descending {
        background-color: #ffffff30;
        box-shadow: .1px .1px 10.px #aaa;
    }

     

    Uma abordagem diferente para adicionar ordenação

    Uma outra forma de adicionar ordem é criar um formulário com uma opção para escolher cada coluna (com um pouco de JavaScript, você também pode usar as headers para seleção), direcionar a uma view que usa a função .order_by(“column name”) no objeto globals e retorná-las ordenadas na função render. As duas opções estão implementadas no meu  GitHub se quiser dar uma olhada. Preste atenção ao fato que, no primeiro método, não estamos mudando os dados ou o conjunto de resultados. Já que estamos apenas ajustando a forma que é exibida, não afeta a exportação.

     

    Mais uma dica sobre o JavaScript

    Aqui eu preparei só mais uma coisa para você que pode ser útil ao usar Django e JavaScript. Se quiser redirecionar a uma URL (por exemplo, o update), você pode usar document.location.href = “update”; no arquivo .js.

     

    Por que eu iria querer saber tudo isso se sou um desenvolvedor IRIS?

    Você pode ter notado que esse artigo inteiro não usou o IRIS diretamente. Os tutoriais da parte 2 seriam muito similares se estivéssemos usando qualquer outra base de dados. Porém, se conseguimos construir tudo explicado acima usando a tecnologia InterSystems como base, podemos adaptar esse portal para mostrar muito mais com facilidade. Se você já é um desenvolvedor IRIS, pode imaginar facilmente como esse simples portal pode combinar informações de múltiplas origens (não necessariamente globais), além da habilidade de providenciar todo tipo de tratamento e análise de dados, com as ferramentas de Cloud, IntegratedML (Machine Learning), Business Inteligence, Text Analytics e Natural Language Processing (NLP0, etc. Quando todas as ferramentas da InterSystems se encontram com uma completa, fácil e bonita interação com o usuário, fornecida com toda segurança necessária, as possibilidades vão além da imaginação.

    Aqui eu coletei alguns exemplos para ilustrar meu ponto. Você pode ter uma máquina sensorial que envia informações à InterSystems Callin API ,integrada com um programa C++. Essa data pode ser interpretada, tratada e guardada no IRIS e sua análise pode ser exibida com Django, permitindo ao usuário interagir com ela. Combinando com o InterSystems IRIS for Health e HealthShare, esse portal rapidamente se torna uma ferramenta de rastreio para pacientes em terapia. Ele pode usar Machine Learning e BI para detectar e prever mudanças perigosas e enviar alertas com SAM (System Alerting and Monitoring) ao doutor responsável, que pode ser exibido no portal junto com toda infor,ação sobre o caso necessária pra tomar uma decisão rápida.

    Em outro contexto, mas com uma lógica similar, o InterSystems IRIS for Supply Chain pode ser usado com esse portal para permitir que o usuário veja o que pode estar comprometendo a conformidade do sistema. Tal colaboração nos permite fazer e transmitir decisões de uma maneira que toda a operação seja facilmente compreendida e controlada.

    Comentarios (0)1
    Inicie sesión o regístrese para continuar
    Pregunta
    · 8 jul, 2024

    How to handle line break inside NTE segment inside HL7 message

    I have an HL7 message that contains NTE segment with line break inside.

    when I try to transform it (with DTL) it stops reading the message after the line break inside the NTE because it treat that as "End of Message".

    Is there a way to solve this in the DTL or I need to run a pre process on the HL7 message that identify the line break inside the NTE segments and replace it with an escape char?

    1 Comentario
    Comentarios (1)3
    Inicie sesión o regístrese para continuar