{"context":{"domain":"ramon-playground"},"layers":{"ApplicationLayer":{"reference":"ApplicationLayer","availableInstances":[{"reference":"ComponentsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@DataSet","reference":"SystemsDataSet","params":{"filter":{"domain":"data2"},"pagination":{"size":1},"datasource":{"component":"data2-core-types@ProcessReference","params":{"reference":"SystemsDataSource"}}}},{"reference":"ExternalComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"SystemsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"5e3b796d6228227ca637d0f4","name":"data2","domain":"data2","organization":"62292184611f480b3191c37c","visibility":"public","updatedAt":"2022-03-09T02:01:26.213Z"}]}},{"reference":"OrganizationsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"DataComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@DataSet","reference":"OneFileComponentInstancesDataSet","params":{"pagination":{"size":1},"master":{"dataset":{"component":"data2-core-types@ProcessReference","params":{"reference":"SystemsDataSet"}},"localField":"system","masterField":"_id"},"datasource":{"component":"data2-core-types@ProcessReference","params":{"reference":"FileComponentInstancesDataSource"}}}},{"reference":"ApplicationsDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"ComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"ServiceComponentInstancesDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@Data2TableDataSource","reference":"FileComponentInstancesDataSource","params":{"table":"fileComponentInstances","schema":[{"component":"data2-core-types@Field","params":{"key":"component","title":"Component","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"system","title":"System","component":"data2-core-primitives@ObjectId"}},{"component":"data2-core-types@Field","params":{"key":"displayName","title":"Display Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"params","title":"Params","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"key":"reference","title":"Reference","component":"data2-core-primitives@String"}}]}},{"component":"data2-core@MemoryDataSource","reference":"EmptyDataSource","params":{"initialData":[]}},{"reference":"ComponentsDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"UserComponentsDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"DataComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ServiceComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ExternalComponentInstancesDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}},{"reference":"ApplicationsDataSet","component":"data2-core@DataSet","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"EmptyDataSource"}}}}],"processesParams":{}},"HostApplicationLayer":{"reference":"HostApplicationLayer","availableInstances":[{"_id":"5f15ff190528b92601890f71","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"SystemsTableDataSource"}},"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"domain"}}},"pk":"_id","fields":[{"component":"data2-core-types@FieldReference","params":{"key":"_id"}},{"component":"data2-core-types@FieldReference","params":{"key":"name"}},{"component":"data2-core-types@FieldReference","params":{"key":"domain"}},{"component":"data2-core-types@FieldReference","params":{"key":"visibility"}},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"customDomains"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization._id"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization.name"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization.billingStatus"}}},"break":true},{"component":"data2-core-types@FieldReference","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"organization.publicTrial.active"}}},"break":true}],"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}},"staticPagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}},"policies":[{"component":"data2-core-auth@Policy","params":{"allow":{"params":{"actions":[{"params":{"components":[{"params":{"query":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$params.query"}}}},"field":{"component":"data2-core-primitives@String","params":{"content":"_id"}},"fieldType":"string"},"component":"data2@7KkQq0vK4a7D2gg6IVJT7"},{"params":{"query":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$params.query"}}}},"field":{"component":"data2-core-primitives@String","params":{"content":"domain"}},"fieldType":"string"},"component":"data2@7KkQq0vK4a7D2gg6IVJT7"},{"params":{"query":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$params.query"}}}},"field":{"component":"data2-core-primitives@String","params":{"content":"customDomains"}},"fieldType":"string"},"component":"data2@7KkQq0vK4a7D2gg6IVJT7"}]},"component":"data2-core-logical-operators@Or"}]},"component":"data2-core-flow@Series"}}}]},"reference":"SystemsDataSet","updatedAt":"2025-11-05T19:23:47.135Z","createdAt":"2020-07-20T20:31:21.838Z"},{"_id":"5f1601ce0528b92601890f7c","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":1000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentsTableDataSource"}},"sort":{"params.package":1,"params.component":1},"pk":"_id","autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"staticFilter":{"system":{"exists":{"params":{"content":false},"component":"data2-core-primitives@Boolean"}}},"filter":{"system":{"exists":{"params":{"content":false},"component":"data2-core-primitives@Boolean"}}}},"reference":"ComponentsDataSet","updatedAt":"2025-11-05T19:37:01.935Z","createdAt":"2020-07-20T20:42:54.898Z"},{"_id":"5f9041dbc8da12be8b94aea4","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":2000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentsTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"UserComponentsDataSet","updatedAt":"2025-11-06T21:06:58.095Z","createdAt":"2020-07-20T20:44:09.350Z"},{"_id":"65d8c4fabc9dbb8f94de8d53","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ExternalComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ExternalComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:23.742Z","createdAt":"2024-02-23T16:17:01.816Z"},{"reference":"SystemsTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"686bd23e4fcbdb9728476ebc","name":"Ramon Playground","domain":"ramon-playground","visibility":"public","updatedAt":"2025-07-07T12:56:41.025Z","createdAt":"2025-07-07T12:56:41.025Z"}]}},{"reference":"ComponentsTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"5f52a278a575399a45d239b4","component":"data2-core-types@Component","params":{"package":"data2-core-primitives","component":"Router","interactions":{"component":"data2-core-types@FieldSet","params":{"fields":{"goBack":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-types@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@This","params":{}},"prop":"history.goBack","args":[]}}}},"icon":{"component":"data2-core-primitives@String","params":{"content":"arrow-left"}},"visibility":"public"}},"goTo":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@This","params":{}},"prop":"history.push","args":[{"component":"data2-core-types@Reference","params":{"reference":"url"}},{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"preserveQuery"}}}}]}},"parameters":[{"component":"data2-core-primitives@String","params":{"content":"url"}},{"component":"data2-core-primitives@String","params":{"content":"preserveQuery"}}]},"break":true},"icon":{"component":"data2-core-primitives@String","params":{"content":"share"}},"visibility":"public","arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Path to route"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Path to redirect user"}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"},{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Boolean"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Preserve Query"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Preserve query string parameters  preserve query parameters on navigating."}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"}]}},"open":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-types@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"component":"data2-core-types@This","params":{}},"prop":"history.push","args":[{"pathname":{"component":"data2-core-types@Reference","params":{"reference":"value"}}}]}},"parameters":["value"]}},"icon":{"component":"data2-core-primitives@String","params":{"content":"share"}},"visibility":"public","arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Link to open"}},"description":{"component":"data2-core-primitives@String","params":{"content":""}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"},{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Target"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Where to open the link"}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"oneOf":[{"params":{"content":"_blank"},"component":"data2-core-primitives@String"},{"params":{"content":"_self"},"component":"data2-core-primitives@String"},{"params":{"content":"_parent"},"component":"data2-core-primitives@String"},{"params":{"content":"_top"},"component":"data2-core-primitives@String"}]},"component":"data2-core-types@ComponentParameter"}]}},"close":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-types@Function"}},"definition":{"component":"data2-core-functions@Function","params":{"body":{"preventEvaluation":true,"component":"data2-core-types@Getter","params":{"module":{"params":{},"component":"data2-core-web@Window"},"prop":"close"}},"parameters":["value"]}},"icon":{"component":"data2-core-primitives@String","params":{"content":"times"}},"visibility":"public","arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Link to open"}},"description":{"component":"data2-core-primitives@String","params":{"content":""}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2-core-types@ComponentParameter"},{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Target"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Where to open the link"}},"visibility":"public","required":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"oneOf":[{"params":{"content":"_blank"},"component":"data2-core-primitives@String"},{"params":{"content":"_self"},"component":"data2-core-primitives@String"},{"params":{"content":"_parent"},"component":"data2-core-primitives@String"},{"params":{"content":"_top"},"component":"data2-core-primitives@String"}]},"component":"data2-core-types@ComponentParameter"}],"description":{"component":"data2-core-primitives@String","params":{"content":"Closes a window that was opened via router.open."}}}}}}}}},{"_id":"620d28658271aa4129919d89","component":"data2-core-types@Component","params":{"package":"data2-interface-services","component":"DeviceController","interactions":{"params":{"fields":{"postMessage":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":"data2-core-primitives@String","title":{"component":"data2-core-primitives@String","params":{"content":"data"}}}}]},"component":"data2-core-types@ComponentParameter"},"print":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Object"}},"flat":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"parameters":{"zoom":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Number"}},"title":{"component":"data2-core-primitives@String","params":{"content":"zoom"}},"visibility":"public"}}},"visibility":"public"},"component":"data2-core-types@ComponentParameter"}],"visibility":"public"},"component":"data2-core-types@ComponentParameter"},"share":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}}},"component":"data2-core-types@ComponentParameter"},"clipboard.copy":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}}}}]},"component":"data2-core-types@ComponentParameter"},"clipboard.paste":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}}}}]},"component":"data2-core-types@ComponentParameter"},"download":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Filename"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Content"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Object"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Options"}},"parameters":{"params":{"fields":{"type":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Mimetype"}}}}}},"component":"data2-core-types@FieldSet"}}}]},"component":"data2-core-types@ComponentParameter"},"downloadUrl":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Filename"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Url"}}}}]},"component":"data2-core-types@ComponentParameter"},"promptFiles":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":"data2-core-primitives@Object","flat":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"parameters":{"params":{"fields":{"multiple":{"component":"data2-core-types@ComponentParameter","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Multiple"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Whether or not to allow selecting multiple files"}},"component":"data2-core-primitives@Boolean"}},"acceptedFormats":{"component":"data2-core-types@ComponentParameter","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Accepted Formats"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Accepted file formats"}},"component":"data2-core-primitives@String","list":{"component":"data2-core-primitives@Boolean","params":{"content":true}}}},"timeout":{"component":"data2-core-types@ComponentParameter","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Timeout"}},"description":{"component":"data2-core-primitives@String","params":{"content":"Max milliseconds to wait for file upload"}},"component":"data2-core-primitives@Number"}}}},"component":"data2-core-types@FieldSet"}}}],"visibility":"public"},"component":"data2-core-types@ComponentParameter"},"meetingRecord":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","definition":{"params":{"actions":[{"params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"meeting"}},"script":{"component":"data2-core-primitives@String","params":{"content":"(function() {\n  let mediaRecorder;\n  let audioChunks = [];\n  let combinedStream;\n  let audioContext;\n  \n  window.meetingCapture = async function() {\n    try {\n      // Solicitar acesso ao áudio da guia (e vídeo, que será ignorado depois)\n      const tabStream = await navigator.mediaDevices.getDisplayMedia({ \n        video: true, // Necessário para alguns navegadores\n        audio: true\n      });\n      \n      // Remover a trilha de vídeo\n      const tabAudioTrack = tabStream.getAudioTracks()[0];\n      \n      // Solicitar acesso ao microfone\n      const micStream = await navigator.mediaDevices.getUserMedia({ audio: true });\n      const micAudioTrack = micStream.getAudioTracks()[0];\n      \n      // Criar um novo MediaStream com ambas as trilhas de áudio\n      combinedStream = new MediaStream([tabAudioTrack, micAudioTrack]);\n      \n      // Criar um contexto de áudio para misturar os streams\n      audioContext = new AudioContext();\n      const destination = audioContext.createMediaStreamDestination();\n      \n      // Conectar a trilha de áudio da guia\n      const tabSource = audioContext.createMediaStreamSource(new MediaStream([tabAudioTrack]));\n      tabSource.connect(destination);\n      \n      // Conectar a trilha de áudio do microfone\n      const micSource = audioContext.createMediaStreamSource(new MediaStream([micAudioTrack]));\n      micSource.connect(destination);\n      \n      // Iniciar gravação com o stream misturado\n      mediaRecorder = new MediaRecorder(destination.stream);\n      audioChunks = [];\n      mediaRecorder.ondataavailable = (e) => audioChunks.push(e.data);\n      mediaRecorder.start();\n      \n      console.log('Gravação iniciada. Chame meetingCaptureStop() para finalizar.');\n    } catch (error) {\n      console.error('Erro ao iniciar a captura:', error);\n    }\n  };\n  \n  window.meetingCaptureStop = function() {\n    return new Promise((resolve, reject) => {\n      if (!mediaRecorder) {\n        reject('Nenhuma gravação em andamento.');\n        return;\n      }\n      \n      mediaRecorder.onstop = () => {\n        const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });\n        combinedStream.getTracks().forEach(track => track.stop());\n        audioContext.close();\n        \n        resolve(audioBlob);\n        console.log('Gravação finalizada. O arquivo de áudio está pronto para upload.');\n      };\n      \n      mediaRecorder.stop();\n    });\n  };\n})();"}}},"component":"data2-core-web@Script"},{"component":"data2-core-types@Getter","params":{"module":{"params":{},"component":"data2-core-web@Window"},"prop":{"component":"data2-core-primitives@String","params":{"content":"meetingCapture"}}}}]},"component":"data2-core-flow@Series"}},"component":"data2-core-types@ComponentParameter"},"meetingRecordStop":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"public","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Filename"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Content"}}}},{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Object"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Options"}},"parameters":{"params":{"fields":{"type":{"component":"data2-core-types@ComponentParameter","params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@String"}},"title":{"component":"data2-core-primitives@String","params":{"content":"Mimetype"}}}}}},"component":"data2-core-types@FieldSet"}}}],"definition":{"params":{"actions":[{"component":"data2-core-types@Getter","params":{"module":{"params":{},"component":"data2-core-web@Window"},"prop":{"component":"data2-core-primitives@String","params":{"content":"meetingCaptureStop"}}}}]},"component":"data2-core-flow@Series"}},"component":"data2-core-types@ComponentParameter"},"notify":{"params":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core-primitives@Function"}},"visibility":"private","arguments":[{"component":"data2-core-types@ComponentParameter","params":{"component":"data2-core-primitives@Object","parameters":{"title":{"params":{"component":"data2-core-primitives@String","index":{"component":"data2-core-primitives@Number","params":{"content":0}},"title":{"component":"data2-core-primitives@String","params":{"content":"title"}}},"component":"data2-core-types@ComponentParameter"},"sound":{"params":{"component":"data2-core-types@FileComponentUrlReference","index":{"component":"data2-core-primitives@Number","params":{"content":1}},"title":{"component":"data2-core-primitives@String","params":{"content":"sound"}}},"component":"data2-core-types@ComponentParameter"}},"flat":{"component":"data2-core-primitives@Boolean","params":{"content":true}}}}]},"component":"data2-core-types@ComponentParameter"}}},"component":"data2-core-types@FieldSet"}}},{"_id":"6a46a7aad17c9b3315acebd7","component":"data2-core-types@Component","system":"686bd23e4fcbdb9728476ebc","params":{"extends":"data2-core-primitives@Block","component":"TmTaskBoard","package":"ramon-playground","definition":{"preventEvaluation":true,"component":"data2-core-types@Definition","params":{"def":{"component":"data2-code-components@CodeHost","params":{"code":{"component":"data2-core-primitives@String","params":{"content":"// Data2 Tasks Manager — Kanban board (code component)\n// Datasets: tasks (TM Tasks), comments (TM Comments), boards (TM Boards), users (TM Users)\n// Regra central: status avança APENAS sequencialmente (nunca retrocede).\n// \"Cancel\" é terminal e pode ser aplicado a partir de qualquer status não-terminal.\n// Boards: cada task pertence a um board (boardId); membros filtram por pessoa\n// (assigneeId); quem cria o board é o admin (adminId) — só ele edita/apaga/gerencia membros.\n\nconst FLOW = [\n  'Backlog',\n  'In Progress',\n  'Code Review',\n  'Development Ok',\n  'Validating / Test',\n  'Ready for Review',\n  'Ready for Deploy',\n  'Deploy',\n  'Done',\n];\nconst CANCEL = 'Cancel';\nconst COLUMNS = FLOW.concat(CANCEL);\n\nconst COLORS = {\n  'Backlog': '#64748b',\n  'In Progress': '#3b82f6',\n  'Code Review': '#8b5cf6',\n  'Development Ok': '#06b6d4',\n  'Validating / Test': '#f59e0b',\n  'Ready for Review': '#eab308',\n  'Ready for Deploy': '#f97316',\n  'Deploy': '#14b8a6',\n  'Done': '#22c55e',\n  'Cancel': '#ef4444',\n};\n\nconst esc = (s) => String(s == null ? '' : s).replace(/[&<>\"']/g, (c) => (\n  { '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' }[c]\n));\n\n// Próximo status na sequência — null se já é o último (Done) ou fora do fluxo (Cancel).\nconst nextOf = (status) => {\n  const i = FLOW.indexOf(status);\n  return i >= 0 && i < FLOW.length - 1 ? FLOW[i + 1] : null;\n};\nconst isTerminal = (status) => status === 'Done' || status === CANCEL;\n\n// Guarda anti-regressão: só aceita mover para o PRÓXIMO status ou para Cancel.\nconst canMove = (from, to) => {\n  if (isTerminal(from)) return false;\n  if (to === CANCEL) return true;\n  return to === nextOf(from);\n};\n\n// Sessão: gravada no localStorage pelo TmLogin (fonte da verdade do usuário logado).\nfunction getSession() {\n  try {\n    const raw = localStorage.getItem('tm_auth_user');\n    const u = raw ? JSON.parse(raw) : null;\n    return (u && u.email && u.role) ? u : null; // só é válida com email E role\n  } catch (err) { return null; }\n}\n\nconst commentsOf = (comments, taskId) =>\n  comments\n    .filter((c) => String(c.taskId) === String(taskId))\n    .sort((a, b) => String(a.createdAt || '').localeCompare(String(b.createdAt || '')));\n\n// ── Boards & pessoas ─────────────────────────────────────────────────────────\nconst AVATAR_COLORS = ['#f59e0b', '#3b82f6', '#8b5cf6', '#10b981', '#ef4444', '#06b6d4', '#e11d48', '#84cc16'];\nconst initialsOf = (name) => String(name || '?').trim().split(/\\s+/).map((p) => p[0]).slice(0, 2).join('').toUpperCase();\nconst colorFor = (seed) => {\n  let h = 0; const s = String(seed || '');\n  for (let i = 0; i < s.length; i++) h = ((h * 31) + s.charCodeAt(i)) >>> 0;\n  return AVATAR_COLORS[h % AVATAR_COLORS.length];\n};\nconst isMember = (board, userId) => !!board && (\n  String(board.adminId) === String(userId) ||\n  (Array.isArray(board.memberIds) && board.memberIds.some((id) => String(id) === String(userId)))\n);\nconst boardsOf = (boards, userId) => boards.filter((b) => isMember(b, userId));\nconst membersOf = (board, users) => {\n  if (!board) return [];\n  const ids = (Array.isArray(board.memberIds) ? board.memberIds : []).map(String);\n  if (board.adminId && !ids.includes(String(board.adminId))) ids.unshift(String(board.adminId));\n  return ids.map((id) => users.find((u) => String(u._id) === id)).filter(Boolean);\n};\n\nfunction renderCard(d2, t, commentCount, assignee) {\n  const color = COLORS[t.status] || '#64748b';\n  const desc = String(t.description || '');\n  const snippet = desc.length > 90 ? desc.slice(0, 90) + '…' : desc;\n  const dragging = d2.state.drag && String(d2.state.drag.id) === String(t._id);\n  return `\n    <div class=\"tm-card${dragging ? ' tm-dragging' : ''}\" draggable=\"${isTerminal(t.status) ? 'false' : 'true'}\"\n         data-key=\"${esc(t._id)}\" data-id=\"${esc(t._id)}\" data-status=\"${esc(t.status)}\">\n      <div class=\"tm-card-title\">${esc(t.title)}</div>\n      ${snippet ? `<div class=\"tm-card-desc\">${esc(snippet)}</div>` : ''}\n      <div class=\"tm-card-foot\">\n        <span class=\"tm-foot-left\">\n          ${t.code ? `<span class=\"tm-code\">${esc(t.code)}</span>` : ''}\n          <span class=\"tm-badge\" style=\"background:${color}1a;color:${color}\">${esc(t.status)}</span>\n        </span>\n        <span class=\"tm-meta\">\n          ${commentCount ? `<span class=\"tm-cc\" title=\"comentários\">💬 ${commentCount}</span>` : ''}\n          ${t.createdAt ? `<span class=\"tm-date\">${esc(d2.fmt.date(t.createdAt))}</span>` : ''}\n          ${assignee ? `<span class=\"tm-ass\" title=\"${esc(assignee.name)}\" style=\"background:${colorFor(assignee.name)}\">${esc(initialsOf(assignee.name))}</span>` : ''}\n        </span>\n      </div>\n    </div>`;\n}\n\nfunction renderColumn(d2, status, tasks, comments, users) {\n  const color = COLORS[status] || '#64748b';\n  const cards = tasks\n    .map((t) => renderCard(d2, t, commentsOf(comments, t._id).length,\n      (users || []).find((u) => String(u._id) === String(t.assigneeId || ''))))\n    .join('');\n  // Feedback visual do drag: apenas a coluna do PRÓXIMO status é alvo válido.\n  let drop = '';\n  const drag = d2.state.drag;\n  if (drag && !isTerminal(drag.from)) {\n    const valid = status === nextOf(drag.from);\n    if (valid) drop = d2.state.over === status ? ' tm-drop-ok tm-drop-over' : ' tm-drop-ok';\n    else if (status !== drag.from) drop = ' tm-drop-no';\n  }\n  return `\n    <div class=\"tm-col${drop}\" data-key=\"col-${esc(status)}\" data-status=\"${esc(status)}\">\n      <div class=\"tm-col-head\">\n        <span class=\"tm-dot\" style=\"background:${color}\"></span>\n        <span class=\"tm-col-name\" title=\"${esc(status)}\">${esc(status)}</span>\n        <span class=\"tm-count\">${tasks.length}</span>\n      </div>\n      <div class=\"tm-col-body\">${cards || '<div class=\"tm-empty\">—</div>'}</div>\n    </div>`;\n}\n\nfunction renderNewModal(d2, members, myId) {\n  return `\n    <div class=\"tm-backdrop tm-backdrop-close\">\n      <div class=\"tm-modal\">\n        <div class=\"tm-modal-head\">\n          <h2>Nova tarefa</h2>\n          <button class=\"tm-x tm-close\" title=\"Fechar\">✕</button>\n        </div>\n        <label class=\"tm-label\">Título</label>\n        <input class=\"tm-input\" id=\"tm-new-title\" placeholder=\"O que precisa ser feito?\" maxlength=\"140\"/>\n        <label class=\"tm-label\">Descrição</label>\n        <textarea class=\"tm-input tm-area\" id=\"tm-new-desc\" rows=\"5\" placeholder=\"Detalhes da tarefa (opcional)\"></textarea>\n        <label class=\"tm-label\">Responsável</label>\n        <select class=\"tm-input\" id=\"tm-new-assignee\">\n          ${(members || []).map((m) => `<option value=\"${esc(m._id)}\" ${String(m._id) === String(myId) ? 'selected' : ''}>${esc(m.name)}</option>`).join('')}\n        </select>\n        <div class=\"tm-hint\">Status inicial: <b>Backlog</b> (automático)</div>\n        ${d2.state.formErr ? `<div class=\"tm-err-msg\">${esc(d2.state.formErr)}</div>` : ''}\n        <div class=\"tm-actions\">\n          <button class=\"tm-btn tm-ghost tm-close\">Cancelar</button>\n          <button class=\"tm-btn tm-primary tm-create\" ${d2.state.busy ? 'disabled' : ''}>\n            ${d2.state.busy ? 'Criando…' : 'Criar tarefa'}\n          </button>\n        </div>\n      </div>\n    </div>`;\n}\n\nfunction renderDetailModal(d2, t, comments, users) {\n  const color = COLORS[t.status] || '#64748b';\n  const list = commentsOf(comments, t._id);\n  const next = nextOf(t.status);\n  const terminal = isTerminal(t.status);\n  const assignee = (users || []).find((u) => String(u._id) === String(t.assigneeId || ''));\n  const rows = list\n    .map((c) => `\n      <div class=\"tm-comment\" data-key=\"${esc(c._id)}\">\n        <div class=\"tm-comment-text\">${esc(c.text)}</div>\n        <div class=\"tm-comment-date\">${c.createdAt ? esc(d2.fmt.relative(c.createdAt)) : ''}</div>\n      </div>`)\n    .join('');\n  return `\n    <div class=\"tm-backdrop tm-backdrop-close\">\n      <div class=\"tm-modal tm-modal-lg\">\n        <div class=\"tm-modal-head\">\n          <span class=\"tm-foot-left\">\n            ${t.code ? `<span class=\"tm-code tm-code-lg\">${esc(t.code)}</span>` : ''}\n            <span class=\"tm-badge tm-badge-lg\" style=\"background:${color}1a;color:${color}\">${esc(t.status)}</span>\n          </span>\n          <button class=\"tm-x tm-close\" title=\"Fechar\">✕</button>\n        </div>\n        <h2 class=\"tm-detail-title\">${esc(t.title)}</h2>\n        ${t.description ? `<p class=\"tm-detail-desc\">${esc(t.description)}</p>` : '<p class=\"tm-detail-desc tm-muted\">Sem descrição.</p>'}\n        ${assignee ? `<div class=\"tm-hint\" style=\"margin:0 0 10px\">Responsável:\n          <span class=\"tm-ass\" style=\"background:${colorFor(assignee.name)}\">${esc(initialsOf(assignee.name))}</span>\n          <b>${esc(assignee.name)}</b></div>` : ''}\n\n        <div class=\"tm-flow\">\n          ${terminal\n            ? `<div class=\"tm-hint\">Tarefa em estado final — não pode mais ser movida.</div>`\n            : `<label class=\"tm-select-wrap\">\n                 <span class=\"tm-select-label\">Status</span>\n                 <select class=\"tm-input tm-status-select\" data-id=\"${esc(t._id)}\" ${d2.state.busy ? 'disabled' : ''}>\n                   <option value=\"\" selected>${esc(t.status)} (atual)</option>\n                   ${next ? `<option value=\"${esc(next)}\">${esc(next)}</option>` : ''}\n                 </select>\n               </label>\n               <button class=\"tm-btn tm-danger tm-cancel-task\" data-id=\"${esc(t._id)}\" ${d2.state.busy ? 'disabled' : ''}>Cancelar tarefa</button>`}\n        </div>\n        <div class=\"tm-hint tm-flow-hint\">Fluxo: ${FLOW.map((s) => (s === t.status ? `<b>${esc(s)}</b>` : esc(s))).join(' → ')}</div>\n\n        <div class=\"tm-sep\"></div>\n        <h3 class=\"tm-h3\">Comentários (${list.length})</h3>\n        <div class=\"tm-comments\">${rows || '<div class=\"tm-muted\">Nenhum comentário ainda.</div>'}</div>\n        <div class=\"tm-comment-form\">\n          <textarea class=\"tm-input tm-area\" id=\"tm-comment-text\" rows=\"3\" placeholder=\"Escreva um comentário…\"></textarea>\n          <button class=\"tm-btn tm-primary tm-add-comment\" data-id=\"${esc(t._id)}\" ${d2.state.busy ? 'disabled' : ''}>\n            ${d2.state.busy ? 'Salvando…' : 'Comentar'}\n          </button>\n        </div>\n      </div>\n    </div>`;\n}\n\n// Minha conta: ver dados e alterar nome (+ senha opcional). E-mail NUNCA é\n// editável e a senha atual NUNCA é exibida (aparece como ********).\nfunction renderAccountModal(d2, me, allUsers) {\n  const rec = (allUsers || []).find((x) => String(x._id) === String(me._id)) || me;\n  return `\n    <div class=\"tm-backdrop\">\n      <div class=\"tm-modal\">\n        <div class=\"tm-modal-head\">\n          <h2>Minha conta</h2>\n          <button class=\"tm-x tm-acc-close\" title=\"Fechar\">✕</button>\n        </div>\n        <div class=\"tm-acc-id\">\n          <span class=\"tm-avatar\" style=\"background:${colorFor(rec.name)}\">${esc(initialsOf(rec.name))}</span>\n          <span class=\"tm-user-role\">${esc(rec.role || '')}</span>\n        </div>\n        <label class=\"tm-label\">Nome</label>\n        <input class=\"tm-input\" id=\"acc-name\" value=\"${esc(rec.name || '')}\" maxlength=\"60\"/>\n        <label class=\"tm-label\">E-mail (não pode ser alterado)</label>\n        <input class=\"tm-input\" value=\"${esc(rec.email || '')}\" disabled/>\n        <label class=\"tm-label\">Senha atual</label>\n        <input class=\"tm-input\" value=\"********\" disabled/>\n        <label class=\"tm-label\">Nova senha (opcional)</label>\n        <input class=\"tm-input\" id=\"acc-pass\" type=\"password\" placeholder=\"deixe em branco para manter a atual\"/>\n        ${d2.state.accErr ? `<div class=\"tm-err-msg\">${esc(d2.state.accErr)}</div>` : ''}\n        ${d2.state.accMsg ? `<div class=\"tm-ok-msg\">${esc(d2.state.accMsg)}</div>` : ''}\n        <div class=\"tm-actions\">\n          <button class=\"tm-btn tm-ghost tm-acc-close\">Fechar</button>\n          <button class=\"tm-btn tm-primary tm-acc-save\" ${d2.state.busy ? 'disabled' : ''}>${d2.state.busy ? 'Salvando…' : 'Salvar'}</button>\n        </div>\n      </div>\n    </div>`;\n}\n\n// Tela de gerenciamento de boards: criar (criador vira admin); editar/apagar e\n// gerenciar membros SÓ para o admin do board.\nfunction renderManager(d2, myBoards, allUsers, myId) {\n  const rows = myBoards.map((b) => {\n    const admin = String(b.adminId) === String(myId);\n    const editing = String(d2.state.editBid || '') === String(b._id);\n    const members = membersOf(b, allUsers);\n    const memberIds = members.map((m) => String(m._id));\n    const addable = allUsers.filter((u) => !memberIds.includes(String(u._id)));\n    const head = editing\n      ? `<div class=\"tm-mgr-editform\">\n           <input class=\"tm-input tm-mgr-in-icon\" id=\"mgr-edit-icon\" value=\"${esc(b.icon || '')}\" maxlength=\"4\" placeholder=\"📋\"/>\n           <input class=\"tm-input\" id=\"mgr-edit-name\" value=\"${esc(b.boardName || '')}\" maxlength=\"60\" placeholder=\"Nome do board\"/>\n           <input class=\"tm-input\" id=\"mgr-edit-desc\" value=\"${esc(b.description || '')}\" maxlength=\"140\" placeholder=\"Descrição\"/>\n           <button class=\"tm-btn tm-primary tm-mgr-save\" data-bid=\"${esc(b._id)}\" ${d2.state.busy ? 'disabled' : ''}>Salvar</button>\n           <button class=\"tm-btn tm-ghost tm-mgr-cancel-edit\">Cancelar</button>\n         </div>`\n      : `<div class=\"tm-mgr-boardhead\">\n           <span class=\"tm-mgr-icon\">${esc(b.icon || '📋')}</span>\n           <div class=\"tm-mgr-names\">\n             <div class=\"tm-mgr-name\">${esc(b.boardName)} ${admin ? '<span class=\"tm-side-admin\">admin</span>' : ''}</div>\n             <div class=\"tm-mgr-desc\">${esc(b.description || '')}</div>\n           </div>\n           ${admin ? `<span class=\"tm-mgr-actions\">\n             <button class=\"tm-btn tm-ghost tm-mgr-edit\" data-bid=\"${esc(b._id)}\">Editar</button>\n             <button class=\"tm-btn tm-danger tm-mgr-delete\" data-bid=\"${esc(b._id)}\" ${d2.state.busy ? 'disabled' : ''}>Apagar</button>\n           </span>` : ''}\n         </div>`;\n    const chips = members.map((m) => `\n      <span class=\"tm-member-chip\" data-key=\"mc-${esc(b._id)}-${esc(m._id)}\">\n        <span class=\"tm-avatar tm-avatar-xs\" style=\"background:${colorFor(m.name)}\">${esc(initialsOf(m.name))}</span>\n        ${esc(m.name)}${String(m._id) === String(b.adminId) ? ' 👑' : ''}\n        ${admin && String(m._id) !== String(b.adminId)\n          ? `<button class=\"tm-chip-x tm-mgr-remove-member\" data-bid=\"${esc(b._id)}\" data-uid=\"${esc(m._id)}\" title=\"Remover do board\">✕</button>` : ''}\n      </span>`).join('');\n    const addRow = admin && addable.length ? `\n      <div class=\"tm-mgr-addrow\">\n        <select class=\"tm-input\" id=\"mgr-add-${esc(b._id)}\">\n          <option value=\"\">Adicionar pessoa…</option>\n          ${addable.map((u) => `<option value=\"${esc(u._id)}\">${esc(u.name)} (${esc(u.role)})</option>`).join('')}\n        </select>\n        <button class=\"tm-btn tm-primary tm-mgr-add-member\" data-bid=\"${esc(b._id)}\" ${d2.state.busy ? 'disabled' : ''}>Adicionar</button>\n      </div>` : '';\n    return `\n      <div class=\"tm-mgr-board\" data-key=\"mgr-${esc(b._id)}\">\n        ${head}\n        <div class=\"tm-mgr-members\">${chips || '<span class=\"tm-muted\">Sem membros.</span>'}</div>\n        ${addRow}\n      </div>`;\n  }).join('');\n\n  return `\n    <div class=\"tm-backdrop\">\n      <div class=\"tm-modal tm-modal-lg\">\n        <div class=\"tm-modal-head\">\n          <h2>Gerenciar boards</h2>\n          <button class=\"tm-x tm-mgr-close\" title=\"Fechar\">✕</button>\n        </div>\n        <div class=\"tm-mgr-createrow\">\n          <input class=\"tm-input tm-mgr-in-icon\" id=\"mgr-icon\" maxlength=\"4\" placeholder=\"📋\"/>\n          <input class=\"tm-input\" id=\"mgr-name\" maxlength=\"60\" placeholder=\"Nome do novo board\"/>\n          <input class=\"tm-input\" id=\"mgr-desc\" maxlength=\"140\" placeholder=\"Descrição (opcional)\"/>\n          <button class=\"tm-btn tm-primary tm-mgr-create\" ${d2.state.busy ? 'disabled' : ''}>Criar</button>\n        </div>\n        <div class=\"tm-hint\">Quem cria o board vira o admin dele — pode editar, apagar e gerenciar as pessoas.</div>\n        ${d2.state.mgrErr ? `<div class=\"tm-err-msg\">${esc(d2.state.mgrErr)}</div>` : ''}\n        <div class=\"tm-sep\"></div>\n        <div class=\"tm-mgr-list\">${rows || '<div class=\"tm-muted\">Nenhum board ainda — crie o primeiro acima.</div>'}</div>\n      </div>\n    </div>`;\n}\n\nexport default {\n  css: `\n    * { box-sizing: border-box; }\n    .tm-app { display: flex; flex-direction: row; height: 100%; background: #f4f5f7;\n      font: 14px/1.45 -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; color: #172b4d; }\n    .tm-sidebar { width: 232px; flex: none; background: #fff; border-right: 1px solid #e2e4ea; }\n    .tm-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }\n    .tm-code { font-size: 10px; font-weight: 700; color: #6b778c; letter-spacing: .02em; white-space: nowrap; }\n    .tm-code-lg { font-size: 13px; }\n    .tm-foot-left { display: flex; align-items: center; gap: 8px; min-width: 0; }\n    .tm-select-wrap { display: flex; align-items: center; gap: 8px; }\n    .tm-select-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: #6b778c; }\n    .tm-status-select { width: auto; min-width: 220px; cursor: pointer; }\n\n    .tm-topbar { display: flex; align-items: center; gap: 12px; padding: 14px 20px;\n      background: #fff; border-bottom: 1px solid #e2e4ea; }\n    .tm-title { font-size: 17px; font-weight: 700; margin: 0; }\n    .tm-sub { color: #6b778c; font-size: 12px; }\n    .tm-spacer { flex: 1; }\n    .tm-user { display: flex; align-items: center; gap: 8px; margin-right: 4px; }\n    .tm-user-btn { display: inline-flex; align-items: center; gap: 7px; cursor: pointer; padding: 4px 8px; border-radius: 8px; }\n    .tm-user-btn:hover { background: #eef0f3; }\n    .tm-acc-id { display: flex; align-items: center; gap: 10px; margin: 4px 0 6px; }\n    .tm-ok-msg { margin-top: 10px; font-size: 12px; color: #15803d; background: #dcfce7; border-radius: 6px; padding: 6px 10px; }\n    .tm-user-name { font-size: 12.5px; font-weight: 600; }\n    .tm-user-role { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;\n      background: #e8efff; color: #2563eb; border-radius: 4px; padding: 2px 7px; }\n    .tm-logout { padding: 6px 10px; font-size: 12px; }\n\n    .tm-board { flex: 1; display: flex; gap: 6px; padding: 10px 12px; overflow-x: auto; align-items: stretch; }\n    .tm-col { flex: 1 1 0; min-width: 152px; display: flex; flex-direction: column;\n      background: #eef0f3; border-radius: 8px; max-height: 100%; }\n    .tm-col-head { display: flex; align-items: center; gap: 4px; padding: 6px 7px; }\n    .tm-dot { width: 6px; height: 6px; border-radius: 50%; flex: none; }\n    .tm-col-name { font-size: 9px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; color: #44546f;\n      white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n    .tm-count { margin-left: auto; background: #dfe2e8; border-radius: 10px; padding: 0 5px; font-size: 9px; color: #44546f; flex: none; }\n    .tm-col-body { flex: 1; overflow-y: auto; padding: 2px 5px 6px; display: flex; flex-direction: column; gap: 5px; }\n    .tm-empty { color: #a5adba; text-align: center; padding: 8px 0; font-size: 10px; }\n\n    .tm-card { background: #fff; border-radius: 6px; padding: 6px 8px; font-size: 11.5px; cursor: grab;\n      box-shadow: 0 1px 2px rgba(9,30,66,.12); border: 1px solid transparent; transition: box-shadow .12s, border-color .12s; }\n    .tm-card:hover { border-color: #b3c4ff; box-shadow: 0 2px 6px rgba(9,30,66,.16); }\n    .tm-card:active { cursor: grabbing; }\n    .tm-card[draggable=\"false\"] { cursor: pointer; }\n    .tm-dragging { opacity: .35; }\n    .tm-col { border: 2px dashed transparent; transition: background .12s, border-color .12s, opacity .12s; }\n    .tm-drop-ok { border-color: #2563eb; background: #e8efff; }\n    .tm-drop-ok .tm-col-name { color: #2563eb; }\n    .tm-drop-over { background: #d7e4ff; box-shadow: inset 0 0 0 2px #2563eb; }\n    .tm-drop-no { opacity: .5; }\n    .tm-card-title { font-weight: 600; margin-bottom: 2px; word-break: break-word; font-size: 11.5px; }\n    .tm-card-desc { color: #6b778c; font-size: 10px; margin-bottom: 5px; word-break: break-word;\n      display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }\n    .tm-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 4px; flex-wrap: wrap; }\n    .tm-badge { font-size: 8px; font-weight: 700; padding: 1px 5px; border-radius: 3px; white-space: nowrap;\n      overflow: hidden; text-overflow: ellipsis; max-width: 100%; }\n    .tm-badge-lg { font-size: 12px; padding: 4px 10px; }\n    .tm-meta { display: flex; align-items: center; gap: 8px; color: #6b778c; font-size: 11px; }\n\n    .tm-btn { border: 0; border-radius: 6px; padding: 8px 14px; font-weight: 600; font-size: 13px; cursor: pointer; }\n    .tm-btn:disabled { opacity: .55; cursor: default; }\n    .tm-primary { background: #2563eb; color: #fff; }\n    .tm-primary:hover:not(:disabled) { background: #1d4ed8; }\n    .tm-ghost { background: #eef0f3; color: #172b4d; }\n    .tm-danger { background: #fee2e2; color: #b91c1c; }\n    .tm-danger:hover:not(:disabled) { background: #fecaca; }\n\n    .tm-backdrop { position: fixed; inset: 0; background: rgba(9,30,66,.45); display: flex;\n      align-items: flex-start; justify-content: center; padding: 48px 16px; z-index: 50; overflow-y: auto; }\n    .tm-modal { background: #fff; border-radius: 12px; width: 480px; max-width: 100%; padding: 20px 22px;\n      box-shadow: 0 12px 32px rgba(9,30,66,.25); }\n    .tm-modal-lg { width: 640px; }\n    .tm-modal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }\n    .tm-modal-head h2 { margin: 0; font-size: 16px; }\n    .tm-x { border: 0; background: transparent; font-size: 15px; cursor: pointer; color: #6b778c; padding: 4px 6px; }\n    .tm-x:hover { color: #172b4d; }\n\n    .tm-label { display: block; font-size: 11px; font-weight: 700; text-transform: uppercase;\n      letter-spacing: .05em; color: #6b778c; margin: 12px 0 4px; }\n    .tm-input { width: 100%; border: 1px solid #d5d9e0; border-radius: 6px; padding: 8px 10px;\n      font: inherit; color: inherit; background: #fff; }\n    .tm-input:focus { outline: 2px solid #93b4ff; border-color: #2563eb; }\n    .tm-area { resize: vertical; }\n    .tm-hint { font-size: 12px; color: #6b778c; margin-top: 10px; }\n    .tm-err-msg { margin-top: 10px; font-size: 12px; color: #b91c1c; background: #fee2e2; border-radius: 6px; padding: 6px 10px; }\n    .tm-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }\n\n    .tm-detail-title { margin: 6px 0 4px; font-size: 20px; word-break: break-word; }\n    .tm-detail-desc { margin: 0 0 14px; color: #44546f; white-space: pre-wrap; word-break: break-word; }\n    .tm-muted { color: #a5adba; }\n    .tm-flow { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }\n    .tm-flow-hint { font-size: 11px; margin-top: 2px; }\n    .tm-sep { height: 1px; background: #e2e4ea; margin: 14px 0; }\n    .tm-h3 { margin: 0 0 8px; font-size: 13px; text-transform: uppercase; letter-spacing: .05em; color: #6b778c; }\n    .tm-comments { display: flex; flex-direction: column; gap: 8px; max-height: 220px; overflow-y: auto; }\n    .tm-comment { background: #f4f5f7; border-radius: 8px; padding: 8px 12px; }\n    .tm-comment-text { white-space: pre-wrap; word-break: break-word; }\n    .tm-comment-date { font-size: 11px; color: #6b778c; margin-top: 4px; }\n    .tm-comment-form { display: flex; gap: 8px; margin-top: 10px; align-items: flex-start; }\n    .tm-comment-form .tm-area { flex: 1; }\n\n    .tm-load, .tm-err { display: flex; align-items: center; justify-content: center; height: 100%; color: #6b778c; }\n    .tm-err { color: #b91c1c; }\n    .tm-login-host { height: 100%; }\n\n    .tm-sidebar { display: flex; flex-direction: column; }\n    .tm-side-brand { padding: 16px 16px 8px; font-size: 15px; font-weight: 700; }\n    .tm-side-brand b { color: #2563eb; }\n    .tm-side-title { padding: 10px 16px 4px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: #6b778c; }\n    .tm-side-list { flex: 1; overflow-y: auto; padding: 4px 8px; display: flex; flex-direction: column; gap: 2px; }\n    .tm-side-item { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: 8px; cursor: pointer; font-size: 13px; }\n    .tm-side-item:hover { background: #eef0f3; }\n    .tm-side-active { background: #e8efff; color: #2563eb; font-weight: 600; }\n    .tm-side-icon { font-size: 15px; }\n    .tm-side-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n    .tm-side-admin { font-size: 9px; font-weight: 700; text-transform: uppercase; background: #fef3c7; color: #b45309; border-radius: 4px; padding: 1px 5px; }\n    .tm-side-empty { color: #a5adba; font-size: 12px; padding: 8px 10px; }\n    .tm-manage-btn { margin: 8px 12px 14px; font-size: 12px; }\n\n    .tm-avatars { display: flex; align-items: center; margin-left: 10px; flex: none; }\n    .tm-avatar { width: 30px; height: 30px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;\n      color: #fff; font-size: 11px; font-weight: 700; border: 2px solid #fff; box-shadow: 0 1px 2px rgba(9,30,66,.2); flex: none; }\n    .tm-avatar-btn { cursor: pointer; margin-left: -7px; transition: transform .1s; }\n    .tm-avatar-btn:first-child { margin-left: 0; }\n    .tm-avatar-btn:hover { transform: translateY(-2px); }\n    .tm-avatar-sel { outline: 2px solid #2563eb; outline-offset: 1px; }\n    .tm-avatar-xs { width: 20px; height: 20px; font-size: 8.5px; border-width: 1px; }\n    .tm-clear-person { margin-left: 10px; padding: 5px 9px; font-size: 11px; }\n    .tm-ass { width: 18px; height: 18px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;\n      color: #fff; font-size: 7.5px; font-weight: 700; flex: none; vertical-align: middle; }\n\n    .tm-mgr-createrow { display: flex; gap: 8px; align-items: center; }\n    .tm-mgr-createrow .tm-input { width: auto; flex: 1; min-width: 100px; }\n    .tm-mgr-in-icon { flex: none !important; width: 54px !important; text-align: center; }\n    .tm-mgr-list { display: flex; flex-direction: column; gap: 12px; max-height: 420px; overflow-y: auto; }\n    .tm-mgr-board { border: 1px solid #e2e4ea; border-radius: 10px; padding: 12px 14px; }\n    .tm-mgr-boardhead { display: flex; align-items: center; gap: 10px; }\n    .tm-mgr-icon { font-size: 20px; }\n    .tm-mgr-names { flex: 1; min-width: 0; }\n    .tm-mgr-name { font-weight: 700; }\n    .tm-mgr-desc { font-size: 12px; color: #6b778c; }\n    .tm-mgr-actions { display: flex; gap: 6px; }\n    .tm-mgr-actions .tm-btn { padding: 5px 10px; font-size: 11.5px; }\n    .tm-mgr-editform { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }\n    .tm-mgr-editform .tm-input { width: auto; flex: 1; min-width: 110px; }\n    .tm-mgr-members { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }\n    .tm-member-chip { display: inline-flex; align-items: center; gap: 6px; background: #f4f5f7; border-radius: 14px;\n      padding: 3px 9px 3px 3px; font-size: 12px; }\n    .tm-chip-x { border: 0; background: transparent; color: #6b778c; cursor: pointer; font-size: 10px; padding: 0 2px; }\n    .tm-chip-x:hover { color: #b91c1c; }\n    .tm-mgr-addrow { display: flex; gap: 8px; margin-top: 10px; align-items: center; }\n    .tm-mgr-addrow .tm-input { width: auto; flex: 1; }\n    .tm-mgr-addrow .tm-btn { padding: 6px 12px; font-size: 12px; flex: none; }\n  `,\n\n  render(d2) {\n    // ── GUARDA DE AUTENTICAÇÃO ──\n    // d2.state.authAt muda no login/logout e força re-render; getSession() lê a\n    // sessão do localStorage. Sem sessão → renderiza a tela de login EMBUTIDA\n    // (via d2.render) e reage ao callback onAuthed. Zero dependência de router.\n    void d2.state.authAt; // marca dependência reativa\n    const authedUser = getSession();\n    const inBuilder = d2.context && d2.context.isBuilder;\n    if (!authedUser && !inBuilder) {\n      return `<div class=\"tm-login-host\">${d2.render('ramon-playground@TmLogin', {}, {\n        key: 'tm-login',\n        onAuthed: () => { d2.state.authAt = (d2.state.authAt || 0) + 1; },\n      })}</div>`;\n    }\n\n    const ds = d2.data('tasks');\n    const cs = d2.data('comments');\n    const bs = d2.data('boards');\n    const us = d2.data('users');\n    if (!ds) return `<div class=\"tm-err\">Parâmetro “tasks” não conectado a um dataset.</div>`;\n    if (ds.loading) return `<div class=\"tm-load\">Carregando tarefas…</div>`;\n\n    const tasks = ds.records();\n    const comments = cs ? cs.records() : [];\n    const allBoards = bs ? bs.records() : [];\n    const allUsers = us ? us.records() : [];\n\n    // Board atual: derivado — o usuário cai SEMPRE num board dele (o selecionado\n    // no sidebar, senão o PRIMEIRO atribuído). No builder mostra todos.\n    const myId = authedUser ? String(authedUser._id) : null;\n    const myBoards = myId ? boardsOf(allBoards, myId) : allBoards;\n    const board = myBoards.find((b) => String(b._id) === String(d2.state.boardId || '')) || myBoards[0] || null;\n    const members = membersOf(board, allUsers);\n    // Filtro MULTI-pessoa (clique nos avatares alterna cada um) — só valem os\n    // membros do board atual; ids fora dele são ignorados automaticamente.\n    const rawSel = Array.isArray(d2.state.personIds) ? d2.state.personIds.map(String) : [];\n    const personIds = rawSel.filter((id) => members.some((m) => String(m._id) === id));\n\n    const boardTasks = board ? tasks.filter((t) => String(t.boardId || '') === String(board._id)) : [];\n    const visible = personIds.length\n      ? boardTasks.filter((t) => personIds.includes(String(t.assigneeId || '')))\n      : boardTasks;\n\n    const cols = COLUMNS\n      .map((status) => renderColumn(d2, status, visible.filter((t) => t.status === status), comments, allUsers))\n      .join('');\n\n    let modal = '';\n    if (d2.state.view === 'new') {\n      modal = renderNewModal(d2, members, myId);\n    } else if (d2.state.view) {\n      const t = tasks.find((x) => String(x._id) === String(d2.state.view));\n      modal = t ? renderDetailModal(d2, t, comments, allUsers) : '';\n    }\n    const manager = d2.state.screen === 'manager' ? renderManager(d2, myBoards, allUsers, myId) : '';\n    const account = d2.state.screen === 'account' && authedUser ? renderAccountModal(d2, authedUser, allUsers) : '';\n\n    // chip do usuário logado — clicável: abre \"Minha conta\" (canto superior direito)\n    const u = authedUser;\n    const uName = u ? ((allUsers.find((x) => String(x._id) === String(u._id)) || u).name || u.email || '') : '';\n    const userChip = u ? `\n      <div class=\"tm-user\">\n        <span class=\"tm-user-btn\" title=\"Minha conta\">\n          <span class=\"tm-avatar tm-avatar-xs\" style=\"background:${colorFor(uName)}\">${esc(initialsOf(uName))}</span>\n          <span class=\"tm-user-name\">${esc(uName)}</span>\n          <span class=\"tm-user-role\">${esc(u.role || '')}</span>\n        </span>\n        <button class=\"tm-btn tm-ghost tm-logout\">Sair</button>\n      </div>` : (inBuilder ? '<div class=\"tm-user\"><span class=\"tm-user-role\">builder preview</span></div>' : '');\n\n    // sidebar: todos os boards do usuário logado\n    const sideItems = myBoards.map((b) => `\n      <div class=\"tm-side-item${board && String(b._id) === String(board._id) ? ' tm-side-active' : ''}\"\n           data-key=\"side-${esc(b._id)}\" data-bid=\"${esc(b._id)}\">\n        <span class=\"tm-side-icon\">${esc(b.icon || '📋')}</span>\n        <span class=\"tm-side-name\">${esc(b.boardName)}</span>\n        ${myId && String(b.adminId) === myId ? '<span class=\"tm-side-admin\">admin</span>' : ''}\n      </div>`).join('');\n\n    // avatares dos membros do board atual — clique alterna a pessoa no filtro (multi)\n    const avatars = members.map((m) => `\n      <span class=\"tm-avatar tm-avatar-btn${personIds.includes(String(m._id)) ? ' tm-avatar-sel' : ''}\"\n            data-key=\"av-${esc(m._id)}\" data-uid=\"${esc(m._id)}\" title=\"${esc(m.name)}\"\n            style=\"background:${colorFor(m.name)}\">${esc(initialsOf(m.name))}</span>`).join('');\n\n    return `\n      <div class=\"tm-app\">\n        <aside class=\"tm-sidebar\">\n          <div class=\"tm-side-brand\">Data2 <b>Tasks</b></div>\n          <div class=\"tm-side-title\">Meus boards</div>\n          <div class=\"tm-side-list\">${sideItems || '<div class=\"tm-side-empty\">Você não está em nenhum board ainda.</div>'}</div>\n          <button class=\"tm-btn tm-ghost tm-manage-btn\">⚙️ Gerenciar boards</button>\n        </aside>\n        <div class=\"tm-main\">\n          <div class=\"tm-topbar\">\n            <div>\n              <h1 class=\"tm-title\">${board ? `${esc(board.icon || '')} ${esc(board.boardName)}` : 'Data2 Tasks Manager'}</h1>\n              <div class=\"tm-sub\">${board ? `${esc(board.description || '')} · ` : ''}${visible.length} tarefa(s)${personIds.length ? ` · filtrado por ${personIds.length} pessoa(s)` : ''} · arraste o card para a próxima coluna</div>\n            </div>\n            <div class=\"tm-avatars\">${avatars}${personIds.length ? '<button class=\"tm-btn tm-ghost tm-clear-person\">Todos</button>' : ''}</div>\n            <div class=\"tm-spacer\"></div>\n            ${userChip}\n            <button class=\"tm-btn tm-primary tm-new-btn\" ${board ? '' : 'disabled'}>+ Nova tarefa</button>\n          </div>\n          ${board\n            ? `<div class=\"tm-board\">${cols}</div>`\n            : '<div class=\"tm-load\">Você não pertence a nenhum board — peça a um admin para te adicionar, ou crie um em “Gerenciar boards”.</div>'}\n        </div>\n        ${modal}\n        ${manager}\n        ${account}\n      </div>`;\n  },\n\n  mounted(d2) {\n    const close = () => { d2.state.view = null; d2.state.formErr = null; };\n    let dragEndedAt = 0; // suprime o clique fantasma que alguns browsers disparam após o drop\n\n    // Canal robusto de login: o TmLogin embutido dispara 'tm-auth-changed' no window\n    // após gravar a sessão; aqui o board reage e re-renderiza (mostra o quadro).\n    d2.on(window, 'tm-auth-changed', () => { d2.state.authAt = (d2.state.authAt || 0) + 1; });\n\n    d2.on('.tm-new-btn', 'click', () => { d2.state.formErr = null; d2.state.view = 'new'; });\n    d2.on('.tm-close', 'click', close);\n    d2.on('.tm-backdrop-close', 'click', (e, el) => { if (e.target === el) close(); });\n    d2.on('.tm-card', 'click', (e, el) => {\n      if (Date.now() - dragEndedAt < 200) return;\n      d2.state.formErr = null; d2.state.view = el.dataset.id;\n    });\n\n    // ── Drag & drop: mover APENAS para o próximo status ─────────────────────\n    d2.on('.tm-card', 'dragstart', (e, el) => {\n      const from = el.dataset.status;\n      if (isTerminal(from)) { e.preventDefault(); return; } // Done/Cancel não arrastam\n      e.dataTransfer.setData('text/plain', String(el.dataset.id));\n      e.dataTransfer.effectAllowed = 'move';\n      const id = el.dataset.id;\n      // adia o re-render para não abortar o drag nativo do browser\n      setTimeout(() => { d2.state.drag = { id, from }; }, 0);\n    });\n\n    d2.on('.tm-col', 'dragover', (e, el) => {\n      const drag = d2.state.drag;\n      if (!drag) return;\n      const to = el.dataset.status;\n      // preventDefault SÓ na coluna do próximo status → o browser recusa o drop nas demais\n      if (to === nextOf(drag.from)) {\n        e.preventDefault();\n        e.dataTransfer.dropEffect = 'move';\n        if (d2.state.over !== to) d2.state.over = to;\n      }\n    });\n\n    d2.on('.tm-col', 'dragleave', (e, el) => {\n      if (e.relatedTarget && el.contains(e.relatedTarget)) return; // ainda dentro da coluna\n      if (d2.state.over === el.dataset.status) d2.state.over = null;\n    });\n\n    d2.on('.tm-col', 'drop', async (e, el) => {\n      e.preventDefault();\n      const drag = d2.state.drag;\n      d2.state.drag = null;\n      d2.state.over = null;\n      if (!drag || d2.state.busy) return;\n      const to = el.dataset.status;\n      // guarda dupla: o alvo precisa ser exatamente o próximo status da origem\n      if (to !== nextOf(drag.from) || !canMove(drag.from, to)) return;\n      const ds = d2.data('tasks');\n      const t = ds.records().find((x) => String(x._id) === String(drag.id));\n      if (!t || t.status !== drag.from) return; // o status mudou durante o drag → aborta\n      d2.state.busy = true;\n      try {\n        await ds.update({ ...t, status: to });\n      } catch (err) {\n        d2.log('tm-dnd error', err);\n      } finally {\n        d2.state.busy = false;\n      }\n    });\n\n    // Logout — limpa a sessão local e re-renderiza (a guarda mostra o login).\n    d2.on('.tm-logout', 'click', () => {\n      try { localStorage.removeItem('tm_auth_user'); } catch (err) { /* storage off */ }\n      d2.state.view = null;\n      d2.state.authAt = (d2.state.authAt || 0) + 1;\n    });\n\n    // limpeza garantida (drop fora de alvo válido, ESC, etc.)\n    d2.on(document, 'dragend', () => {\n      dragEndedAt = Date.now();\n      if (d2.state.drag || d2.state.over) { d2.state.drag = null; d2.state.over = null; }\n    });\n\n    // ── Boards: navegação, filtro por pessoa e gerenciamento ────────────────\n    const myBoardsNow = () => {\n      const me = getSession();\n      const bsd = d2.data('boards');\n      const list = bsd ? bsd.records() : [];\n      return me ? boardsOf(list, String(me._id)) : list;\n    };\n    const currentBoard = () => {\n      const list = myBoardsNow();\n      return list.find((b) => String(b._id) === String(d2.state.boardId || '')) || list[0] || null;\n    };\n    const findBoard = (bid) => {\n      const bsd = d2.data('boards');\n      return (bsd ? bsd.records() : []).find((b) => String(b._id) === String(bid)) || null;\n    };\n\n    d2.on('.tm-side-item', 'click', (e, el) => {\n      d2.state.boardId = el.dataset.bid;\n      d2.state.personIds = [];\n      d2.state.view = null;\n    });\n    // Filtro MULTI-pessoa: cada clique alterna a pessoa dentro/fora da seleção.\n    d2.on('.tm-avatar-btn', 'click', (e, el) => {\n      const uid = String(el.dataset.uid);\n      const cur = Array.isArray(d2.state.personIds) ? d2.state.personIds.map(String) : [];\n      d2.state.personIds = cur.includes(uid) ? cur.filter((id) => id !== uid) : cur.concat(uid);\n    });\n    d2.on('.tm-clear-person', 'click', () => { d2.state.personIds = []; });\n    d2.on('.tm-manage-btn', 'click', () => { d2.state.screen = 'manager'; d2.state.editBid = null; d2.state.mgrErr = null; });\n    d2.on('.tm-mgr-close', 'click', () => { d2.state.screen = null; d2.state.editBid = null; d2.state.mgrErr = null; });\n\n    // ── Minha conta ──────────────────────────────────────────────────────────\n    d2.on('.tm-user-btn', 'click', () => { d2.state.screen = 'account'; d2.state.accErr = null; d2.state.accMsg = null; });\n    d2.on('.tm-acc-close', 'click', () => { d2.state.screen = null; d2.state.accErr = null; d2.state.accMsg = null; });\n\n    // Salvar conta: nome editável + nova senha opcional; e-mail e role intocáveis.\n    d2.on('.tm-acc-save', 'click', async () => {\n      const me = getSession();\n      if (!me || d2.state.busy) return;\n      const usd = d2.data('users');\n      const rec = (usd ? usd.records() : []).find((x) => String(x._id) === String(me._id));\n      if (!rec) { d2.state.accErr = 'Não foi possível carregar seus dados.'; return; }\n      const name = ((d2.$('#acc-name') || {}).value || '').trim();\n      const npass = (d2.$('#acc-pass') || {}).value || '';\n      if (!name) { d2.state.accErr = 'O nome é obrigatório.'; return; }\n      if (npass && npass.length < 4) { d2.state.accErr = 'A nova senha precisa de pelo menos 4 caracteres.'; return; }\n      d2.state.busy = true;\n      try {\n        // e-mail NUNCA muda; senha só muda se uma nova foi informada\n        await usd.update({ ...rec, name, password: npass || rec.password });\n        try { localStorage.setItem('tm_auth_user', JSON.stringify({ ...me, name })); } catch (err) { /* noop */ }\n        const pi = d2.$('#acc-pass'); if (pi) pi.value = '';\n        d2.state.accErr = null;\n        d2.state.accMsg = 'Dados salvos com sucesso.';\n        d2.state.authAt = (d2.state.authAt || 0) + 1;\n      } catch (err) {\n        d2.state.accErr = 'Erro ao salvar. Tente novamente.';\n        d2.log('tm-acc error', err);\n      } finally {\n        d2.state.busy = false;\n      }\n    });\n\n    // Criar board — quem cria vira o admin dele.\n    d2.on('.tm-mgr-create', 'click', async () => {\n      const me = getSession();\n      if (!me || d2.state.busy) return;\n      const name = ((d2.$('#mgr-name') || {}).value || '').trim();\n      const desc = ((d2.$('#mgr-desc') || {}).value || '').trim();\n      const icon = ((d2.$('#mgr-icon') || {}).value || '').trim();\n      if (!name) { d2.state.mgrErr = 'O nome do board é obrigatório.'; return; }\n      d2.state.busy = true;\n      try {\n        await d2.data('boards').create({\n          boardName: name,\n          description: desc,\n          icon: icon || '📋',\n          adminId: String(me._id),\n          memberIds: [String(me._id)],\n          createdAt: new Date().toISOString(),\n        });\n        d2.state.mgrErr = null;\n        ['#mgr-name', '#mgr-desc', '#mgr-icon'].forEach((s) => { const i = d2.$(s); if (i) i.value = ''; });\n      } catch (err) {\n        d2.state.mgrErr = 'Erro ao criar o board.';\n        d2.log('tm-mgr-create error', err);\n      } finally {\n        d2.state.busy = false;\n      }\n    });\n\n    d2.on('.tm-mgr-edit', 'click', (e, el) => { d2.state.editBid = el.dataset.bid; });\n    d2.on('.tm-mgr-cancel-edit', 'click', () => { d2.state.editBid = null; });\n\n    // Salvar edição — só o admin do board.\n    d2.on('.tm-mgr-save', 'click', async (e, el) => {\n      const me = getSession();\n      const b = findBoard(el.dataset.bid);\n      if (!b || !me || String(b.adminId) !== String(me._id) || d2.state.busy) return;\n      const name = ((d2.$('#mgr-edit-name') || {}).value || '').trim();\n      const desc = ((d2.$('#mgr-edit-desc') || {}).value || '').trim();\n      const icon = ((d2.$('#mgr-edit-icon') || {}).value || '').trim();\n      if (!name) { d2.state.mgrErr = 'O nome do board é obrigatório.'; return; }\n      d2.state.busy = true;\n      try {\n        await d2.data('boards').update({ ...b, boardName: name, description: desc, icon: icon || '📋' });\n        d2.state.editBid = null;\n        d2.state.mgrErr = null;\n      } catch (err) {\n        d2.state.mgrErr = 'Erro ao salvar o board.';\n        d2.log('tm-mgr-save error', err);\n      } finally {\n        d2.state.busy = false;\n      }\n    });\n\n    // Apagar board — só o admin, com confirmação.\n    d2.on('.tm-mgr-delete', 'click', async (e, el) => {\n      const me = getSession();\n      const b = findBoard(el.dataset.bid);\n      if (!b || !me || String(b.adminId) !== String(me._id) || d2.state.busy) return;\n      const ok = await d2.dialog.confirm(`Apagar o board “${b.boardName}”? As tasks dele deixarão de aparecer.`);\n      if (!ok) return;\n      d2.state.busy = true;\n      try {\n        await d2.data('boards').remove(b._id);\n        if (String(d2.state.boardId || '') === String(b._id)) d2.state.boardId = null;\n      } catch (err) {\n        d2.state.mgrErr = 'Erro ao apagar o board.';\n        d2.log('tm-mgr-delete error', err);\n      } finally {\n        d2.state.busy = false;\n      }\n    });\n\n    // Adicionar pessoa ao board — só o admin.\n    d2.on('.tm-mgr-add-member', 'click', async (e, el) => {\n      const me = getSession();\n      const b = findBoard(el.dataset.bid);\n      if (!b || !me || String(b.adminId) !== String(me._id) || d2.state.busy) return;\n      const sel = d2.$('#mgr-add-' + el.dataset.bid);\n      const uid = sel && sel.value;\n      if (!uid) return;\n      const ids = (Array.isArray(b.memberIds) ? b.memberIds : []).map(String);\n      if (ids.includes(String(uid))) return;\n      d2.state.busy = true;\n      try {\n        await d2.data('boards').update({ ...b, memberIds: ids.concat(String(uid)) });\n      } catch (err) {\n        d2.state.mgrErr = 'Erro ao adicionar a pessoa.';\n        d2.log('tm-mgr-add error', err);\n      } finally {\n        d2.state.busy = false;\n      }\n    });\n\n    // Remover pessoa do board — só o admin; o próprio admin não pode ser removido.\n    d2.on('.tm-mgr-remove-member', 'click', async (e, el) => {\n      const me = getSession();\n      const b = findBoard(el.dataset.bid);\n      if (!b || !me || String(b.adminId) !== String(me._id) || d2.state.busy) return;\n      const uid = String(el.dataset.uid);\n      if (uid === String(b.adminId)) return; // admin fica\n      d2.state.busy = true;\n      try {\n        const ids = (Array.isArray(b.memberIds) ? b.memberIds : []).map(String).filter((id) => id !== uid);\n        await d2.data('boards').update({ ...b, memberIds: ids });\n        if (Array.isArray(d2.state.personIds) && d2.state.personIds.map(String).includes(uid)) {\n          d2.state.personIds = d2.state.personIds.map(String).filter((id) => id !== uid);\n        }\n      } catch (err) {\n        d2.state.mgrErr = 'Erro ao remover a pessoa.';\n        d2.log('tm-mgr-remove error', err);\n      } finally {\n        d2.state.busy = false;\n      }\n    });\n\n    // Criar tarefa — status SEMPRE inicia em Backlog, no board atual, com responsável.\n    d2.on('.tm-create', 'click', async () => {\n      if (d2.state.busy) return;\n      const title = (d2.$('#tm-new-title') || {}).value || '';\n      const description = (d2.$('#tm-new-desc') || {}).value || '';\n      if (!title.trim()) { d2.state.formErr = 'O título é obrigatório.'; return; }\n      const b = currentBoard();\n      if (!b) { d2.state.formErr = 'Nenhum board selecionado.'; return; }\n      const me = getSession();\n      const assigneeSel = d2.$('#tm-new-assignee');\n      d2.state.busy = true;\n      try {\n        // ID de identificação sequencial: DT-1, DT-2, …\n        const nums = d2.data('tasks').records()\n          .map((x) => { const m = /^DT-(\\d+)$/.exec(String(x.code || '')); return m ? Number(m[1]) : 0; });\n        const code = `DT-${Math.max(0, ...nums) + 1}`;\n        await d2.data('tasks').create({\n          code,\n          title: title.trim(),\n          description: description.trim(),\n          status: 'Backlog',\n          createdAt: new Date().toISOString(),\n          boardId: String(b._id),\n          assigneeId: String((assigneeSel && assigneeSel.value) || (me && me._id) || ''),\n        });\n        close();\n      } catch (err) {\n        d2.state.formErr = 'Erro ao criar a tarefa. Tente novamente.';\n        d2.log('tm-create error', err);\n      } finally {\n        d2.state.busy = false;\n      }\n    });\n\n    // Avançar status via dropdown — a única opção oferecida é o PRÓXIMO da sequência.\n    d2.on('.tm-status-select', 'change', async (e, el) => {\n      const to = el.value;\n      if (!to) return; // re-selecionou o status atual\n      if (d2.state.busy) { el.value = ''; return; }\n      const ds = d2.data('tasks');\n      const t = ds.records().find((x) => String(x._id) === String(el.dataset.id));\n      if (!t) return;\n      // guarda: só aceita exatamente o próximo status (nunca retrocede, nunca pula)\n      if (to !== nextOf(t.status) || !canMove(t.status, to)) { el.value = ''; return; }\n      d2.state.busy = true;\n      try {\n        await ds.update({ ...t, status: to });\n      } catch (err) {\n        d2.log('tm-advance error', err);\n        el.value = '';\n      } finally {\n        d2.state.busy = false;\n      }\n    });\n\n    // Cancelar tarefa — permitido de qualquer status não-terminal.\n    d2.on('.tm-cancel-task', 'click', async (e, el) => {\n      if (d2.state.busy) return;\n      const ds = d2.data('tasks');\n      const t = ds.records().find((x) => String(x._id) === String(el.dataset.id));\n      if (!t || !canMove(t.status, CANCEL)) return;\n      const ok = await d2.dialog.confirm('Cancelar esta tarefa? Essa ação é definitiva.');\n      if (!ok) return;\n      d2.state.busy = true;\n      try {\n        await ds.update({ ...t, status: CANCEL });\n      } catch (err) {\n        d2.log('tm-cancel error', err);\n      } finally {\n        d2.state.busy = false;\n      }\n    });\n\n    // Comentar — salva no dataset comments vinculado ao id da task.\n    d2.on('.tm-add-comment', 'click', async (e, el) => {\n      if (d2.state.busy) return;\n      const input = d2.$('#tm-comment-text');\n      const text = (input && input.value || '').trim();\n      if (!text) return;\n      d2.state.busy = true;\n      try {\n        await d2.data('comments').create({\n          taskId: String(el.dataset.id),\n          text,\n          createdAt: new Date().toISOString(),\n        });\n        if (input) input.value = '';\n      } catch (err) {\n        d2.log('tm-comment-error', err);\n      } finally {\n        d2.state.busy = false;\n      }\n    });\n  },\n};\n"}},"tasks":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"tasks"}}}},"comments":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"comments"}}}},"boards":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"boards"}}}},"users":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"users"}}}}}}}}}},{"_id":"5ed9bed7b9e0891ce913e884","component":"data2-core-types@Component","params":{"package":"data2-core","component":"DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}},{"_id":"5f472ae463c680de4ff296e9","component":"data2-core-types@Component","params":{"package":"data2-core","component":"Data2TableDataSource","extends":"data2-core@DataSource","renderable":{"dimensions":{"disabled":false,"component":"data2-core-types@Dimensions","params":{"width":1366,"exactWidth":false,"exactHeight":false,"height":768}}}}}]}},{"reference":"ExternalComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"_id":"5f060d9b1ca96def42f3c40a","displayName":"Builder AuthStrategy","component":"data2-core@AuthenticationStrategy","system":"5e3b796d6228227ca637d0f4","params":{"credentials":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"verifier":{"component":"data2-core-types@DataSetReference","params":{"reference":"UsersDataSet"}},"sessionShared":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"password":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},"email":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},"resetPassword":{"resetEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"nR6Q9d7qdaPtZhJ28Q8Dy"},"component":"data2-core-types@ArtboardReference"}},"resetSuccessEmail":{"artboard":{"params":{"preventEvaluation":true,"reference":"yPCJBTKo8q1Mw0B_3Kpwl"},"component":"data2-core-types@ArtboardReference"}}},"session":[{"component":"data2-core-types@DataSetColumnReference","params":{"column":"name"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"email"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"password"}},{"component":"data2-core-types@DataSetColumnReference","params":{"column":"status"}}],"sessionMetadata":{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},{"params":{"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"active"}},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.status"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is active user"}]},"component":"data2-core-logical-operators@And","displayName":"is active and has _id"}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $user"},{"params":{"action":{"params":{"pattern":{"component":"data2-core-primitives@String","params":{"content":"@data2.app"}},"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user.email"}}}}},"component":"data2-core-functions@Includes","displayName":"isData2User"},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}},"component":"data2-core-flow@Step"},{"params":{"action":{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.d2_app"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"management"}}]},"component":"data2-core-functions@Includes","displayName":"isData2App Exception"},"resultName":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}},"component":"data2-core-flow@Step"},{"params":{"resultName":{"component":"data2-core-primitives@String","params":{"content":"has_access"}},"action":{"params":{"compare":{"params":{"components":[{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_user"}}}},{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"is_data2_app_exception"}}}}]},"component":"data2-core-logical-operators@Or"},"else":{"params":{"actions":[{"params":{"actions":[{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"component":"data2-core-logical-operators@Not"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check $metadata.system"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":"filter","args":[{"_id":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"compare":{"params":{"subject":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records.length"}}}}},"component":"data2-core-logical-operators@Not","displayName":"systems not found"},"then":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"}},"component":"data2-core-flow@If","displayName":"check system found"},{"params":{"actions":[{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"organization":{"component":"data2-core-types@Getter","params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"cursor.current.organization._id"}}}}}]},"component":"data2-core-types@Interaction"},{"params":{"module":{"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":"filter","args":[{"user":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$user._id"}}}},"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}}]},"component":"data2-core-types@Interaction"}]},"component":"data2-core-flow@Parallel"}]},"component":"data2-core-flow@Series","displayName":"common setup"},{"params":{"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"},"else":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"compare":{"params":{"components":{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"WuUa-VKHhW9uYU0E3-mJ8"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"mapper":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"system"}}],"body":{"params":{"expression":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.visibility"}}}},"defaultCase":{"params":{"content":false},"component":"data2-core-primitives@Boolean"},"cases":[{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"public"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"billing-owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}},{"component":"data2-core-primitives@String","params":{"content":"member"}}]},"component":"data2-core-functions@Includes","displayName":"has role with access"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"comparisonSubject":{"component":"data2-core-primitives@String","params":{"content":"collaborator"}}},"component":"data2-core-comparison-operators@Equal","displayName":"is collaborator"}]},"component":"data2-core-logical-operators@And","displayName":"is org member and collaborator"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is collaborator"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is collaborator and has system access"}]},"component":"data2-core-logical-operators@Or"}}},{"component":"data2-core-flow@Case","params":{"expression":{"component":"data2-core-primitives@String","params":{"content":"private"}},"value":{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"components":[{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal","displayName":"is org member"},{"params":{"pattern":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.role"}}}},"subject":[{"component":"data2-core-primitives@String","params":{"content":"owner"}},{"component":"data2-core-primitives@String","params":{"content":"admin"}}]},"component":"data2-core-functions@Includes","displayName":"is owner/admin"}]},"component":"data2-core-logical-operators@And","displayName":"has org member role with access"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is owner/admin"},{"params":{"components":[{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"Ok6Tsu5XkS7r8PyW_7TyW"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"member"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"member.organization._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system.organization._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"is org member"},{"params":{"array":{"params":{"module":{"disabled":false,"component":"data2-core-types@InteractiveModuleReference","params":{"reference":"NqKAY34n2ffFL64zamp7t"}},"prop":{"component":"data2-core-primitives@String","params":{"content":"data.records"}}},"component":"data2-core-types@Getter"},"filter":{"disabled":false,"component":"data2-core-functions@Function","params":{"parameters":[{"component":"data2-core-primitives@String","params":{"content":"access"}}],"body":{"params":{"subject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"access.system._id"}}}},"comparisonSubject":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"system._id"}}}}},"component":"data2-core-comparison-operators@Equal"}}}},"component":"data2-core-functions@ArrayFind","displayName":"has system access"}]},"component":"data2-core-logical-operators@And","displayName":"is member and has system access"}]},"component":"data2-core-logical-operators@Or","displayName":"is owner/admin or has system access"}}}]},"component":"data2-core-flow@Switch"}}}},"component":"data2-core-functions@ArrayMap"}},"component":"data2-core-logical-operators@And","displayName":"has org member for all systems in request"}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"then":{"params":{"content":true},"component":"data2-core-primitives@Boolean"}},"component":"data2-core-flow@If"}},"component":"data2-core-flow@Step"},{"params":{"then":{"system":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"$metadata.system"}}}}},"else":{"params":{"message":{"component":"data2-core-primitives@String","params":{"content":"Invalid Credentials"}},"code":{"component":"data2-core-primitives@String","params":{"content":"401"}}},"component":"data2-core-types@Error"},"compare":{"component":"data2-core-types@Reference","params":{"reference":{"component":"data2-core-primitives@String","params":{"content":"has_access"}}}}},"component":"data2-core-flow@If"}]},"component":"data2-core-flow@Series"},"sessionExpiresIn":{"component":"data2-core-primitives@Number","params":{"content":604800}},"sessionRenewal":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"reference":"Data2BuilderAuthentication","updatedAt":"2025-10-28T02:48:49.233Z"},{"_id":"5f060ee51ca96def42f3fbd1","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"UsersTableDataSource"}},"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":1}}}},"reference":"UsersDataSet","updatedAt":"2026-03-04T21:16:40.291Z"},{"_id":"68f938cf5fb002e33752a43d","displayName":"InternalApplicationsAuthenticationStrategy","component":"data2-core@AuthenticationStrategy","system":"5e3b796d6228227ca637d0f4","params":{"resetPassword":{"resetEmail":{"artboard":{"params":{"preventEvaluation":true},"component":"data2-core-types@ArtboardReference"}},"resetSuccessEmail":{"artboard":{"params":{"preventEvaluation":true},"component":"data2-core-types@ArtboardReference"}}},"verifier":{"disabled":false,"component":"data2-core-types@DataSetReference","params":{"reference":"InternalApplicationsVerifierDataSet"}},"password":{"disabled":false,"component":"data2-core-types@DataSetColumnReference","params":{"column":"secret"}},"credentials":[{"component":"data2-core-types@FieldReference","params":{"key":"application"}},{"component":"data2-core-types@FieldReference","params":{"key":"secret"}},{"component":"data2-core-types@FieldReference","params":{"key":"status"}}],"session":[{"component":"data2-core-types@FieldReference","params":{"key":"application"}},{"component":"data2-core-types@FieldReference","params":{"key":"secret"}},{"component":"data2-core-types@FieldReference","params":{"key":"status"}}]},"reference":"InternalApplicationsAuthenticationStrategy","updatedAt":"2025-10-22T20:08:54.442Z","createdAt":"2025-10-22T20:04:31.198Z"},{"component":"data2-core@DataSet","reference":"SessionsDataSet","params":{"requiresConfirmation":false,"pk":"key","datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"data2sessionsdatasource"}}}},{"reference":"UsersTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"component":"data2-core@ServerSessionsDataSource","reference":"data2sessionsdatasource","params":{}},{"_id":"5f1600b70528b92601890f75","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ServiceComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ServiceComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:20.208Z","createdAt":"2020-07-20T20:38:15.436Z"},{"_id":"5f1602190528b92601890f7d","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":40000},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ComponentInstancesTableDataSource"}},"sort":{"_id":1},"pk":"_id","autoEdit":true,"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"ComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:07.089Z","createdAt":"2020-07-20T20:44:09.350Z"},{"_id":"5f16017f0528b92601890f7a","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"clientApplicationDomain"}}},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"FileComponentInstancesDataSet","updatedAt":"2023-08-03T16:08:18.193Z","createdAt":"2020-07-20T20:41:35.797Z"},{"_id":"5f1601990528b92601890f7b","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"ApplicationsTableDataSource"}},"pk":"_id","autoEdit":{"component":"data2-core-primitives@Boolean","params":{"content":true}},"master":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"params":{"column":"_id"},"component":"data2-core-types@DataSetColumnReference"}},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"ApplicationsDataSet","updatedAt":"2022-12-13T21:51:13.995Z","createdAt":"2020-07-20T20:42:01.657Z"},{"_id":"5f16172a0528b92601890f85","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"pagination":{"size":{"component":"data2-core-primitives@Number","params":{"content":10000}}},"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"DataComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"policies":{"params":{"allowGet":{"component":"data2-core-primitives@Boolean","params":{"content":true}}},"component":"data2@hkXy-UhMjhyfptdE6_fpW"}},"reference":"DataComponentInstancesDataSet","updatedAt":"2025-11-06T21:07:12.831Z","createdAt":"2020-07-20T22:14:02.097Z"},{"_id":"60ddc1bbda3861ca65407c5a","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"domain":{"component":"data2-core-types@Reference","params":{"reference":"clientApplicationDomain"}}},"pagination":{"size":1},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"}},"reference":"OneFileComponentInstancesDataSet","updatedAt":"2022-02-09T19:44:38.036Z","createdAt":"2020-07-20T20:41:35.797Z"},{"_id":"63ee3d38b8c9838c62fb05fb","displayName":"DriveFileComponentInstancesDataSet","component":"data2-core@DataSet","system":"5e3b796d6228227ca637d0f4","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"FileComponentInstancesTableDataSource"}},"pk":"_id","autoEdit":true,"filter":{"component":{"component":"data2-core-primitives@String","params":{"content":"data2-core@Drive"}}},"master":{"params":{"dataset":{"component":"data2-core-types@DataSetReference","params":{"reference":"SystemsDataSet"}},"localField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"system"}},"masterField":{"component":"data2-core-types@DataSetColumnReference","params":{"column":"_id"}}},"component":"data2-core-types@DataSetMaster"},"autoSelect":{"component":"data2-core-primitives@Boolean","params":{"content":false}}},"reference":"DriveFileComponentInstancesDataSet","updatedAt":"2025-12-04T21:58:32.367Z","createdAt":"2023-02-16T14:27:07.797Z"},{"reference":"ServiceComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}},{"reference":"ComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a46a7c5bf38d38281506132","component":"data2-core-primitives@Artboard","system":"686bd23e4fcbdb9728476ebc","displayName":"Tasks Manager Board","params":{"title":{"component":"data2-core-primitives@String","params":{"content":"Tasks Manager Board"}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}},"position":{"component":"data2-core-types@Position","params":{"x":-2793,"y":-2409,"exactX":-2793.19,"exactY":-2408.76}}},"reference":"1TOPwDENxRehL7O0Ao-SF"},{"_id":"0467f380c303eb28e179837a","parent":"6a46a7c5bf38d38281506132","component":"ramon-playground@TmTaskBoard","system":"686bd23e4fcbdb9728476ebc","displayName":"TmTaskBoard","params":{"tasks":{"component":"data2-core-types@DataSetReference","params":{"reference":"tm-tasksDataSet"}},"comments":{"component":"data2-core-types@DataSetReference","params":{"reference":"tm-commentsDataSet"}},"super":{"position":{"component":"data2-core-types@Position","params":{"x":0,"y":0,"freeTransform":true,"left":true,"right":true,"top":true,"bottom":true}},"dimensions":{"component":"data2-core-types@Dimensions","params":{"width":1440,"height":900}}},"boards":{"component":"data2-core-types@DataSetReference","params":{"reference":"tm-boardsDataSet"}},"users":{"component":"data2-core-types@DataSetReference","params":{"reference":"tm-usersDataSet"}}},"reference":"36D2Q3csAUpM60ZQqUSfO"}]}},{"_id":"5fc4faeec8da12be8bf3d08a","component":"data2-core@Data2TableDataSource","system":"5e3b796d6228227ca637d0f4","params":{"paginate":{"default":1000},"super":{},"table":"fileComponentInstances","schema":[{"component":"data2-core-types@Field","params":{"key":"component","title":"Component","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"system","title":"System","component":"data2-core-primitives@ObjectId"}},{"component":"data2-core-types@Field","params":{"key":"displayName","title":"Display Name","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"params","title":"Params","component":"data2-core-primitives@Object"}},{"component":"data2-core-types@Field","params":{"key":"reference","title":"Reference","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":{"component":"data2-core-primitives@String","params":{"content":"fileId"}},"title":"File ID","component":"data2-core-primitives@ObjectId"},"break":true}],"hooks":{"before":{"all":[{"hook":"softDelete"}],"find":[{"hook":"useCache","options":{"additionalGroupKeys":["$and.0.system","$and.1.system"],"skipCache":true}}],"create":[{"hook":"timestamp","options":{"fields":["createdAt","updatedAt"]}}],"update":[{"hook":"timestamp","options":{"fields":["updatedAt"]}}],"patch":[{"hook":"timestamp","options":{"fields":["updatedAt"]}}]},"after":{"all":[{"hook":"fileUrl","options":{"downloadField":"params.fileUrl","uploadField":"params.uploadFileUrl","enhanceSchema":false}}],"find":[{"hook":"useCache","options":{"additionalGroupKeys":["$and.0.system","$and.1.system"],"skipCache":true}}],"create":[{"hook":"invalidateCache","options":{"additionalGroupKeys":["system"],"secondaryUniqueKeys":["reference"]}},{"hook":"invalidateEnvCache"}],"update":[{"hook":"invalidateCache","options":{"additionalGroupKeys":["system"],"secondaryUniqueKeys":["reference"]}},{"hook":"invalidateEnvCache"}],"patch":[{"hook":"invalidateCache","options":{"additionalGroupKeys":["system"],"secondaryUniqueKeys":["reference"]}},{"hook":"invalidateEnvCache"}],"remove":[{"hook":"invalidateCache","options":{"additionalGroupKeys":["system"],"secondaryUniqueKeys":["reference"]}},{"hook":"invalidateEnvCache"}]}},"multi":["create"],"useEstimatedDocumentCount":true},"reference":"FileComponentInstancesTableDataSource","updatedAt":"2022-12-19T20:42:51.837Z","createdAt":"2020-11-30T13:59:52.294Z"},{"reference":"ApplicationsTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a46a9961035c335342484f8","displayName":"Data2 Tasks Manager","reference":"OaMPR_IkMBtIK2O8Vjv14","params":{"name":{"component":"data2-core-primitives@String","params":{"content":"Data2 Tasks Manager"}},"shortName":{"component":"data2-core-primitives@String","params":{"content":"Tasks"}},"domain":{"component":"data2-core-primitives@String","params":{"content":"tasks"}},"serverSideRendering":{"component":"data2-core-primitives@Boolean","params":{"content":false}},"entryPoint":{"component":"data2-core-types@ComponentInstanceReference","params":{"component":"data2-core-primitives@Artboard","reference":"1TOPwDENxRehL7O0Ao-SF"}},"responseHeaders":{"X-Frame-Options":{"component":"data2-core-primitives@String","params":{"content":""}},"Content-Security-Policy":{"component":"data2-core-primitives@String","params":{"content":""}},"X-XSS-Protection":{"component":"data2-core-primitives@String","params":{"content":""}}}},"system":"686bd23e4fcbdb9728476ebc","component":"data2-core-primitives@Application"}]}},{"reference":"DataComponentInstancesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[{"_id":"6a46b562638dd23931ba9be3","component":"data2-core@DataSet","system":"686bd23e4fcbdb9728476ebc","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"tm-users"}}},"reference":"tm-usersDataSet"},{"_id":"6a4813a5daa510066788866d","component":"data2-core@DataSet","system":"686bd23e4fcbdb9728476ebc","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"tm-boards"}}},"reference":"tm-boardsDataSet"},{"_id":"6a46a6ffc53088741c533522","component":"data2-core@DataSet","system":"686bd23e4fcbdb9728476ebc","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"tm-comments"}}},"reference":"tm-commentsDataSet"},{"_id":"6a46a6fffb4b5485eb735b94","component":"data2-core@DataSet","system":"686bd23e4fcbdb9728476ebc","params":{"datasource":{"component":"data2-core-types@DataSourceReference","params":{"reference":"tm-tasks"}}},"reference":"tm-tasksDataSet"},{"_id":"6a46b561bf38d3828150af48","component":"data2-core@Data2TableDataSource","system":"686bd23e4fcbdb9728476ebc","params":{"table":"tm-users","schema":[{"component":"data2-core-types@Field","params":{"key":"name","title":"Name","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"email","title":"Email","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"password","title":"Password","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"role","title":"Role","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"createdAt","title":"Created At","component":"data2-core-primitives@Date"}}]},"reference":"tm-users"},{"_id":"6a4813a5d39714c42b46fca4","component":"data2-core@Data2TableDataSource","system":"686bd23e4fcbdb9728476ebc","params":{"table":"tm-boards","schema":[{"component":"data2-core-types@Field","params":{"key":"boardName","title":"Board Name","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"description","title":"Description","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"icon","title":"Icon","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"adminId","title":"Admin Id","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"memberIds","title":"Member Ids","component":"data2-core-primitives@Array"}},{"component":"data2-core-types@Field","params":{"key":"createdAt","title":"Created At","component":"data2-core-primitives@Date"}}]},"reference":"tm-boards"},{"_id":"6a46a6ffc53088741c533515","component":"data2-core@Data2TableDataSource","system":"686bd23e4fcbdb9728476ebc","params":{"table":"tm-comments","schema":[{"component":"data2-core-types@Field","params":{"key":"taskId","title":"Task Id","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"text","title":"Text","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"createdAt","title":"Created At","component":"data2-core-primitives@Date"}}]},"reference":"tm-comments"},{"_id":"6a46a6ff52c2becc94e343b4","component":"data2-core@Data2TableDataSource","system":"686bd23e4fcbdb9728476ebc","params":{"table":"tm-tasks","schema":[{"component":"data2-core-types@Field","params":{"key":"title","title":"Title","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"description","title":"Description","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"status","title":"Status","component":"data2-core-primitives@String","required":true}},{"component":"data2-core-types@Field","params":{"key":"createdAt","title":"Created At","component":"data2-core-primitives@Date"}},{"component":"data2-core-types@Field","params":{"key":"code","title":"Code","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"boardId","title":"Board Id","component":"data2-core-primitives@String"}},{"component":"data2-core-types@Field","params":{"key":"assigneeId","title":"Assignee Id","component":"data2-core-primitives@String"}}]},"reference":"tm-tasks"}]}},{"reference":"BundlesTableDataSource","component":"data2-core@MemoryDataSource","params":{"initialData":[]}}],"processesParams":{}}}}